diff --git a/.mailmap b/.mailmap index ff1392139..3f682de40 100644 --- a/.mailmap +++ b/.mailmap @@ -1,3 +1,4 @@ +Alexander A. Klimov Feu Mourek Florian Strohmaier Florian Strohmaier diff --git a/AUTHORS b/AUTHORS index 1ce2e3bf5..bd1705732 100644 --- a/AUTHORS +++ b/AUTHORS @@ -8,4 +8,5 @@ Marius Hein Noah Hilverling Ravi Kumar Kempapura Srinivasa Sukhwinder Dhillon +VerboEse Yonas Habteab diff --git a/CHANGELOG.md b/CHANGELOG.md index 134a88c96..eb5a6fa77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Icinga DB Web Changelog +Please make sure to always read our [Upgrading](https://icinga.com/docs/icinga-db-web/latest/doc/05-Upgrading/) +documentation before switching to a new version. + +## 1.0.0 (2022-06-30) + +First stable release + ## 1.0.0 RC2 (2021-11-12) Second release candidate diff --git a/README.md b/README.md index 45a28a441..b9ed6e818 100644 --- a/README.md +++ b/README.md @@ -4,85 +4,66 @@ ![Build Status](https://github.com/icinga/icingaweb2-module-icingadb/workflows/PHP%20Tests/badge.svg?branch=master) [![Github Tag](https://img.shields.io/github/tag/Icinga/icingaweb2-module-icingadb.svg)](https://github.com/Icinga/icingaweb2-module-icingadb) -![Icinga Logo](https://icinga.com/wp-content/uploads/2014/06/icinga_logo.png) +Icinga DB is a set of components for publishing, synchronizing and +visualizing monitoring data in the Icinga ecosystem, consisting of: -1. [Documentation](#documentation) -2. [Installation](#installation) -3. [Configuration](#configuration) -4. [Migration](#migration) -5. [New Features](#new-features) -6. [Concepts](#concepts) +* Icinga DB Web which connects to both a Redis server and a database to view and work with + most up-to-date monitoring data +* Icinga 2 with its [Icinga DB feature](https://icinga.com/docs/icinga-2/latest/doc/14-features/#icinga-db) enabled, + responsible for publishing the data to the Redis server, i.e. configuration and its runtime updates, check results, state changes, + downtimes, acknowledgements, notifications, and other events such as flapping +* And the [Icinga DB daemon](https://icinga.com/docs/icinga-db), + which synchronizes the data between the Redis server and the database -**Icinga DB Web** pushes your monitoring stack to the next level. - -Based on the lessons learnt with the base monitoring module, it offers a modern -and streamlined design to provide a clear and concise overview of your monitoring -environment. +![Icinga DB Architecture](doc/res/icingadb-architecture.png) ## Documentation -The documentation is located in the [doc/](doc/) directory and also available -on [icinga.com/docs](https://icinga.com/docs/icingadb-web/latest/). - -## Installation - -For installing Icinga DB Web please check the [installation](https://icinga.com/docs/icingadb-web/latest/doc/02-Installation/) -chapter. - -## Configuration - -To configure Icinga DB Web please check the [configuration](https://icinga.com/docs/icingadb-web/latest/doc/03-Configuration/) -chapter. +Icinga DB Web documentation is available at [icinga.com/docs](https://icinga.com/docs/icinga-db-web/latest/). -## Migration +## Features -To migrate from the monitoring module to Icinga DB Web check the [migration](https://icinga.com/docs/icingadb-web/latest/doc/10-Migration/) -chapter. +Icinga DB Web offers a modern and streamlined design to provide a clear and +concise view of your monitoring environment, also with dark and light mode support. -## New Features +![Icinga DB Dashboard](doc/res/icingadb-dashboard.png) -### Multiple List Layouts +### Various List Layouts -The new view switcher displayed in the controls of lists allows to change their layout. -The majority of lists use this to switch between various levels of detail. The service -list below for example uses it to show a check's output at different lengths. +The view switcher allows to control the level of detail displayed in host and service list views: ![View Switcher Preview](doc/res/view-switcher-preview.png) -### New Search With Auto-Completion +### Search with Autocomplete -We have greatly expanded the search functionality in list views. The so called search-bar -allows experienced users full control by keyboard to write their filters. It also aids -with contextual auto completion. There's also an editor for a more easy manipulation. +The search bar in list views can be used for everything from simple searches to creating complex filters. +It allows full keyboard control and also supports contextual auto-completion. +In addition, there is an editor for easier filter creation. ![Searchbar Completion Preview](doc/res/searchbar-completion-preview.png) -### Cleaner Detail Views +### Clean Detail Views -A host's or service's detail view has been restructured to show more details but also -to make more use of the available space. Important details also got moved to the top -so that they are visible right away without having to scroll down. +Host and service detail views are structured to make best use of available space. +Related information is grouped and important information is at the top for instant access without having to scroll down. ![Service Detail Preview](doc/res/service-detail-preview.png) ### Modal Dialogs -Acknowledging a problem, scheduling a downtime or sending a custom notification does -not take you away from where you've been. Instead a modal dialog is shown on top of -your current view. +Any interaction that requires user input, such as acknowledging problems, scheduling downtimes, etc., +shows a modal dialog over the current view to preserve context and focus on interaction. ![Modal Dialog Preview](doc/res/modal-dialog-preview.png) ### Bulk Operations -If you ever wanted to perform really big bulk acknowledgements or downtime schedules, -now is the time for it. Simply filter for the hosts or services you want to operate on -and then click on the little forward icon on the right. No more *shift-click* nightmares! -(Which are still possible, for the die-hard) +Bulk interactions such as scheduling downtimes for multiple objects, acknowledging multiple problems, etc. +are easily accomplished with the `Continue With` control that operates on filtered lists. ![Continue With Preview](doc/res/continue-with-preview.png) -## Concepts +## License -To learn more about our widget/view designs check the [concepts](https://icinga.com/docs/icinga-db/latest/icinga-db-web/doc/11-Concepts/) -chapter. +Icinga DB Web and the Icinga DB Web documentation are licensed under the terms of the +[GNU General Public License Version 2](LICENSE). diff --git a/application/controllers/HostgroupController.php b/application/controllers/HostgroupController.php index 56712b2ab..978489db2 100644 --- a/application/controllers/HostgroupController.php +++ b/application/controllers/HostgroupController.php @@ -59,7 +59,7 @@ public function indexAction() $paginationControl = $this->createPaginationControl($hosts); $viewModeSwitcher = $this->createViewModeSwitcher($paginationControl, $limitControl); - $hostList = (new HostList($hosts)) + $hostList = (new HostList($hosts->execute())) ->setViewMode($viewModeSwitcher->getViewMode()); yield $this->export($hosts); diff --git a/application/controllers/ServicegroupController.php b/application/controllers/ServicegroupController.php index 42c22e6e9..89fb82960 100644 --- a/application/controllers/ServicegroupController.php +++ b/application/controllers/ServicegroupController.php @@ -65,7 +65,7 @@ public function indexAction() $paginationControl = $this->createPaginationControl($services); $viewModeSwitcher = $this->createViewModeSwitcher($paginationControl, $limitControl); - $serviceList = (new ServiceList($services)) + $serviceList = (new ServiceList($services->execute())) ->setViewMode($viewModeSwitcher->getViewMode()); yield $this->export($services); diff --git a/configuration.php b/configuration.php index d6c8fe1ef..6e9501651 100644 --- a/configuration.php +++ b/configuration.php @@ -118,12 +118,12 @@ ); $this->provideRestriction( - 'icingadb/blacklist/routes', + 'icingadb/denylist/routes', $this->translate('Prevent access to routes that are part of the list') ); $this->provideRestriction( - 'icingadb/blacklist/variables', + 'icingadb/denylist/variables', $this->translate('Hide custom variables of Icinga objects that are part of the list') ); @@ -333,15 +333,15 @@ 'icon' => 'cog' ]); $auth = Auth::getInstance(); - $routeBlacklist = []; + $routeDenylist = []; if ($auth->isAuthenticated() && ! $auth->getUser()->isUnrestricted()) { // The empty array is for PHP pre 7.4, older versions require at least a single param for array_merge - $routeBlacklist = array_flip(array_merge([], ...array_map(function ($restriction) { + $routeDenylist = array_flip(array_merge([], ...array_map(function ($restriction) { return StringHelper::trimSplit($restriction); - }, $auth->getRestrictions('icingadb/blacklist/routes')))); + }, $auth->getRestrictions('icingadb/denylist/routes')))); } - if (! array_key_exists('hostgroups', $routeBlacklist)) { + if (! array_key_exists('hostgroups', $routeDenylist)) { $overviewSection->add(N_('Host Groups'), [ 'description' => $this->translate('List host groups'), 'url' => 'icingadb/hostgroups', @@ -350,7 +350,7 @@ ]); } - if (! array_key_exists('servicegroups', $routeBlacklist)) { + if (! array_key_exists('servicegroups', $routeDenylist)) { $overviewSection->add(N_('Service Groups'), [ 'description' => $this->translate('List service groups'), 'url' => 'icingadb/servicegroups', @@ -359,7 +359,7 @@ ]); } - if (! array_key_exists('usergroups', $routeBlacklist)) { + if (! array_key_exists('usergroups', $routeDenylist)) { $overviewSection->add(N_('User Groups'), [ 'description' => $this->translate('List user groups'), 'url' => 'icingadb/usergroups', @@ -368,7 +368,7 @@ ]); } - if (! array_key_exists('users', $routeBlacklist)) { + if (! array_key_exists('users', $routeDenylist)) { $overviewSection->add(N_('Users'), [ 'description' => $this->translate('List users'), 'url' => 'icingadb/users', @@ -463,15 +463,15 @@ $auth = Auth::getInstance(); - $routeBlacklist = []; + $routeDenylist = []; if ($auth->isAuthenticated() && ! $auth->getUser()->isUnrestricted()) { // The empty array is for PHP pre 7.4, older versions require at least a single param for array_merge - $routeBlacklist = array_flip(array_merge([], ...array_map(function ($restriction) { + $routeDenylist = array_flip(array_merge([], ...array_map(function ($restriction) { return StringHelper::trimSplit($restriction); - }, $auth->getRestrictions('icingadb/blacklist/routes')))); + }, $auth->getRestrictions('icingadb/denylist/routes')))); } - if (! array_key_exists('hostgroups', $routeBlacklist)) { + if (! array_key_exists('hostgroups', $routeDenylist)) { $section->add(N_('Host Groups'), [ 'url' => 'icingadb/hostgroups', 'priority' => 50, @@ -480,7 +480,7 @@ ]); } - if (! array_key_exists('servicegroups', $routeBlacklist)) { + if (! array_key_exists('servicegroups', $routeDenylist)) { $section->add(N_('Service Groups'), [ 'url' => 'icingadb/servicegroups', 'priority' => 60, @@ -489,7 +489,7 @@ ]); } - if (! array_key_exists('usergroups', $routeBlacklist)) { + if (! array_key_exists('usergroups', $routeDenylist)) { $section->add(N_('User Groups'), [ 'url' => 'icingadb/usergroups', 'priority' => 70, @@ -498,7 +498,7 @@ ]); } - if (! array_key_exists('users', $routeBlacklist)) { + if (! array_key_exists('users', $routeDenylist)) { $section->add(N_('Users'), [ 'url' => 'icingadb/users', 'priority' => 80, diff --git a/doc/01-About.md b/doc/01-About.md index aa7ffcace..a13333eaa 100644 --- a/doc/01-About.md +++ b/doc/01-About.md @@ -1,73 +1,64 @@ -# About Icinga DB Web +# Icinga DB Web -1. [Installation](#installation) -2. [Configuration](#configuration) -3. [Migration](#migration) -4. [New Features](#new-features) -5. [Concepts](#concepts) +Icinga DB is a set of components for publishing, synchronizing and +visualizing monitoring data in the Icinga ecosystem, consisting of: -**Icinga DB Web** pushes your monitoring stack to the next level. +* Icinga DB Web which connects to both a Redis server and a database to view and work with monitoring data +* Icinga 2 with its [Icinga DB feature](https://icinga.com/docs/icinga-2/latest/14-features/#icinga-db) enabled, + responsible for publishing monitoring configuration, check results, + states changes and history items to the Redis server +* And the [Icinga DB daemon](https://icinga.com/docs/icinga-db/latest/01-About/), + which synchronizes monitoring data between the Redis server and the database -Based on the lessons learnt with the base monitoring module, it offers a modern -and streamlined design to provide a clear and concise overview of your monitoring -environment. +![Icinga DB Architecture](res/icingadb-architecture.png) -## Installation - -For installing Icinga DB Web please check the [installation](02-Installation.md) chapter. - -## Configuration - -To configure Icinga DB Web please check the [configuration](03-Configuration.md) chapter. +## Features -## Migration +Icinga DB Web offers a modern and streamlined design to provide a clear and +concise overview of your monitoring environment, also with dark and light mode support. -To migrate from the monitoring module to Icinga DB Web check the [migration](10-Migration.md) -chapter. +![Icinga DB Dashboard](res/icingadb-dashboard.png) -## New Features +### Various List Layouts -### Multiple List Layouts - -The new view switcher displayed in the controls of lists allows to change their layout. -The majority of lists use this to switch between various levels of detail. The service -list below for example uses it to show a check's output at different lengths. +The view switcher allows to control the level of detail displayed in host and service list views: ![View Switcher Preview](res/view-switcher-preview.png) -### New Search With Auto-Completion +### Search with Autocomplete -We have greatly expanded the search functionality in list views. The so called search-bar -allows experienced users full control by keyboard to write their filters. It also aids -with contextual auto completion. There's also an editor for a more easy manipulation. +The search bar in list views can be used for everything from simple searches to creating complex filters. +It allows full keyboard control and also supports contextual auto-completion. +In addition, there is an editor for easier filter creation. ![Searchbar Completion Preview](res/searchbar-completion-preview.png) -### Cleaner Detail Views +### Clean Detail Views -A host's or service's detail view has been restructured to show more details but also -to make more use of the available space. Important details also got moved to the top -so that they are visible right away without having to scroll down. +Host and service detail views are structured to make best use of available space. +Related information is grouped and important information is at the top for instant access without having to scroll down. ![Service Detail Preview](res/service-detail-preview.png) ### Modal Dialogs -Acknowledging a problem, scheduling a downtime or sending a custom notification does -not take you away from where you've been. Instead a modal dialog is shown on top of -your current view. +Any interaction that requires user input, such as acknowledging problems, scheduling downtimes, etc., +shows a modal dialog over the current view to preserve context and focus on interaction. ![Modal Dialog Preview](res/modal-dialog-preview.png) ### Bulk Operations -If you ever wanted to perform really big bulk acknowledgements or downtime schedules, -now is the time for it. Simply filter for the hosts or services you want to operate on -and then click on the little forward icon on the right. No more *shift-click* nightmares! -(Which are still possible, for the die-hard) +Bulk interactions such as scheduling downtimes for multiple objects, acknowledging multiple problems, etc. +are easily accomplished with the `Continue With` control that operates on filtered lists. ![Continue With Preview](res/continue-with-preview.png) -## Concepts +## Installation + +To install Icinga DB Web see [Installation](02-Installation.md). + +## License -To learn more about our widget/view designs check the [concepts](11-Concepts.md) chapter. +Icinga DB Web and the Icinga DB Web documentation are licensed under the terms of the +GNU General Public License Version 2. diff --git a/doc/02-Installation.md b/doc/02-Installation.md index 9d29db453..344fee722 100644 --- a/doc/02-Installation.md +++ b/doc/02-Installation.md @@ -1,49 +1,273 @@ -# Installation + +# Installing Icinga DB Web -1. [Requirements](#requirements) -2. [Installation](#installation) -3. [Setup](#setup) +The recommended way to install Icinga DB Web is to use prebuilt packages for +all supported platforms from our official release repository. +Please follow the steps listed for your target operating system, +which guide you through setting up the repository and installing Icinga DB Web. -## Requirements +To upgrade an existing Icinga DB Web installation to a newer version, +see the [Upgrading](05-Upgrading.md) documentation for the necessary steps. -* PHP (>= 7.2) -* MySQL or PostgreSQL PHP libraries -* The following PHP modules must be installed: cURL, dom, json, libxml, pdo -* [Icinga DB](https://github.com/Icinga/icingadb) -* [Icinga Web 2](https://github.com/Icinga/icingaweb2) (>= 2.9) -* [Icinga PHP Library (ipl)](https://github.com/Icinga/icinga-php-library) (>= 0.9) -* [Icinga PHP Thirdparty](https://github.com/Icinga/icinga-php-thirdparty) (>= 0.11) -* For exports to PDF the [pdfexport](https://github.com/Icinga/icingaweb2-module-pdfexport) (>= 0.10) - module is required (Optional) +![Icinga DB Web](res/icingadb-web.png) + +Before installing Icinga DB Web, make sure you have installed the +[Icinga DB daemon](https://icinga.com/docs/icinga-db/latest/doc/02-Installation/). + + + +## Adding Icinga Package Repository + +The recommended way to install Icinga DB Web is to use prebuilt packages from our official release repository. + +!!! tip + + If you install Icinga DB Web on a node that has Icinga 2, Icinga DB or Icinga Web installed via packages, + proceed to [installing the Icinga DB Web package](#installing-icinga-db-web-package) as + the repository is already configured. + +Here's how to add the official release repository: + + + +### Amazon Linux 2 Repository + +!!! info + + A paid repository subscription is required for Amazon Linux 2 repositories. Get more information on + [icinga.com/subscription](https://icinga.com/subscription). + + Don't forget to fill in the username and password section with appropriate credentials in the local .repo file. + +```bash +rpm --import https://packages.icinga.com/icinga.key +wget https://packages.icinga.com/subscription/amazon/ICINGA-release.repo -O /etc/yum.repos.d/ICINGA-release.repo +``` + + + + +### CentOS Repository + +```bash +rpm --import https://packages.icinga.com/icinga.key +wget https://packages.icinga.com/centos/ICINGA-release.repo -O /etc/yum.repos.d/ICINGA-release.repo +``` + + + + +### Debian Repository + + +```bash +apt-get update +apt-get -y install apt-transport-https wget gnupg + +wget -O - https://packages.icinga.com/icinga.key | apt-key add - + +DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release); \ + echo "deb https://packages.icinga.com/debian icinga-${DIST} main" > \ + /etc/apt/sources.list.d/${DIST}-icinga.list + echo "deb-src https://packages.icinga.com/debian icinga-${DIST} main" >> \ + /etc/apt/sources.list.d/${DIST}-icinga.list + +apt-get update +``` + + + + +### RHEL Repository + +!!! info + + A paid repository subscription is required for RHEL repositories. Get more information on + [icinga.com/subscription](https://icinga.com/subscription). + + Don't forget to fill in the username and password section with appropriate credentials in the local .repo file. + +```bash +rpm --import https://packages.icinga.com/icinga.key +wget https://packages.icinga.com/subscription/rhel/ICINGA-release.repo -O /etc/yum.repos.d/ICINGA-release.repo +``` + -## Installation + + +### SLES Repository + +!!! info -### Using Packages + A paid repository subscription is required for SLES repositories. Get more information on + [icinga.com/subscription](https://icinga.com/subscription). -We provide a package for supported platforms. Search for `icingadb-web` with your preferred package manager. + Don't forget to fill in the username and password section with appropriate credentials in the local .repo file. -### From Source +```bash +rpm --import https://packages.icinga.com/icinga.key -Please see Icinga Web 2's documentation on [how to install modules](https://icinga.com/docs/icinga-web-2/latest/doc/08-Modules/#installation). -Use `icingadb` as name. +zypper ar https://packages.icinga.com/subscription/sles/ICINGA-release.repo +zypper ref +``` + -## Setup + + +### Ubuntu Repository + + +```bash +apt-get update +apt-get -y install apt-transport-https wget gnupg + +wget -O - https://packages.icinga.com/icinga.key | apt-key add - + +. /etc/os-release; if [ ! -z ${UBUNTU_CODENAME+x} ]; then DIST="${UBUNTU_CODENAME}"; else DIST="$(lsb_release -c| awk '{print $2}')"; fi; \ + echo "deb https://packages.icinga.com/ubuntu icinga-${DIST} main" > \ + /etc/apt/sources.list.d/${DIST}-icinga.list + echo "deb-src https://packages.icinga.com/ubuntu icinga-${DIST} main" >> \ + /etc/apt/sources.list.d/${DIST}-icinga.list + +apt-get update +``` + + +## Installing Icinga DB Web Package + +Use your distribution's package manager to install the `icingadb-web` package as follows: + + + +#### Amazon Linux 2 + +```bash +yum install icingadb-web +``` + + + + +#### CentOS + +!!! info + + Note that installing Icinga DB Web is only supported on CentOS 7 as CentOS 8 is EOL. + +```bash +yum install icingadb-web +``` + + + + +#### Debian / Ubuntu + +```bash +apt-get install icingadb-web +``` + + + +#### RHEL 8 or Later + +```bash +dnf install icingadb-web +``` + +#### RHEL 7 + +```bash +yum install icingadb-web +``` + + + + +#### SLES + +```bash +zypper install icingadb-web +``` + + + + +## Installing Icinga DB Web from Source + + +Please see the Icinga Web documentation on +[how to install modules](https://icinga.com/docs/icinga-web-2/latest/doc/08-Modules/#installation) from source. +Make sure you use `icingadb` as the module name. The following requirements must also be met. + +### Requirements + +* PHP (≥7.2) +* MySQL or PostgreSQL PDO PHP libraries +* The following PHP modules must be installed: `cURL`, `dom`, `json`, `libxml` +* [Icinga DB](https://github.com/Icinga/icingadb) +* [Icinga Web 2](https://github.com/Icinga/icingaweb2) (≥2.9) +* [Icinga PHP Library (ipl)](https://github.com/Icinga/icinga-php-library) (≥0.9) +* [Icinga PHP Thirdparty](https://github.com/Icinga/icinga-php-thirdparty) (≥0.11) + -1. Log in with a privileged user in Icinga Web 2 and enable the module in `Configuration -> Modules -> icingadb`. -Or use the `icingacli` and run `icingacli module enable icingadb`. +## Configuring Icinga DB Web -2. Create a new Icinga Web 2 resource for [Icinga DB's database](https://icinga.com/docs/icingadb/latest/doc/02-Installation/#configuring-mysql) -using the `Configuration -> Application -> Resources` menu. + +The Icinga Web PHP framework is required to configure and run the Icinga DB Web module. +Package installations of `icingadb-web` already set up the necessary dependencies. +If Icinga Web has not been installed or set up before, +you have completed the instructions here and can proceed to + +[install the web server on Amazon Linux](https://icinga.com/docs/icinga-web-2/latest/doc/02-Installation/06-Amazon-Linux/#install-the-web-server), + + +[install the web server on CentOS](https://icinga.com/docs/icinga-web-2/latest/doc/02-Installation/03-CentOS/#install-the-web-server), + + +[install the web server on Debian](https://icinga.com/docs/icinga-web-2/latest/doc/02-Installation/01-Debian/#install-the-web-server), + + +[install the web server on RHEL](https://icinga.com/docs/icinga-web-2/latest/doc/02-Installation/04-RHEL/#install-the-web-server), + + +[install the web server on SLES](https://icinga.com/docs/icinga-web-2/latest/doc/02-Installation/05-SLES/#install-the-web-server), + + +[install the web server on Ubuntu](https://icinga.com/docs/icinga-web-2/latest/doc/02-Installation/02-Ubuntu/#install-the-web-server), + +which will then take you to the web-based setup wizard, which also covers the configuration of Icinga DB Web. + -3. The next step involves telling the module which database resource to use. This can be done in -`Configuration -> Modules -> icingadb -> Database`. Choose the resource you've created just now. +If Icinga Web has been installed but not yet set up, +please visit Icinga Web and follow the web-based setup wizard. +For Icinga Web setups already running, +log in to Icinga Web with a privileged user and follow the steps below to configure the Icinga DB Web module: -4. Finally head over to `Configuration -> Modules -> icingadb -> Redis` and define how the module should connect -with Icinga DB's Redis. +1. Create a new resource for the Icinga DB database via the `Configuration → Application → Resources` menu. +2. Configure the resource you just created as the database connection for the Icinga DB Web module using the + `Configuration → Modules → icingadb → Database` menu. +3. Configure the connection to the Redis server through the `Configuration → Modules → icingadb → Redis` menu. +4. In order to acknowledge problems, force checks, schedule downtimes, etc., + Icinga DB Web needs access to the Icinga 2 API. + For this you need an `ApiUser` object with appropriate permissions on the Icinga 2 side: + +!!! tip -The full configuration is described in its own [chapter](03-Configuration.md). + For single-node setups it is recommended to manage API credentials in the + `/etc/icinga2/conf.d/api-users.conf` file. If you are running a high-availability Icinga 2 setup, + please manage the credentials in the master zone. -If you previously had the monitoring module installed and configured, you might want to [migrate](10-Migration.md) -some settings. +1. Please add the following Icinga 2 configuration and change the password accordingly: + ``` + object ApiUser "icingadb-web" { + password = "CHANGEME" + permissions = [ "actions/*", "objects/modify/*", "objects/query/*", "status/query" ] + } + ``` +2. Restart Icinga 2 for these changes to take effect. +3. Then configure a command transport for Icinga DB Web + using the credentials you just created via the `Configuration → Modules → icingadb → Command Transports` menu. -This concludes the installation. You should now be able to use Icinga DB Web. +If you have previously used the monitoring module, there is an option to [migrate](10-Migration.md) some settings. + diff --git a/doc/02-Installation.md.d/01-Amazon-Linux.md b/doc/02-Installation.md.d/01-Amazon-Linux.md new file mode 100644 index 000000000..c4b2b5019 --- /dev/null +++ b/doc/02-Installation.md.d/01-Amazon-Linux.md @@ -0,0 +1,3 @@ +# Installing Icinga DB Web on Amazon Linux + + diff --git a/doc/02-Installation.md.d/02-CentOS.md b/doc/02-Installation.md.d/02-CentOS.md new file mode 100644 index 000000000..5f4a05b5f --- /dev/null +++ b/doc/02-Installation.md.d/02-CentOS.md @@ -0,0 +1,3 @@ +# Installing Icinga DB Web on CentOS + + diff --git a/doc/02-Installation.md.d/03-Debian.md b/doc/02-Installation.md.d/03-Debian.md new file mode 100644 index 000000000..3097e4d01 --- /dev/null +++ b/doc/02-Installation.md.d/03-Debian.md @@ -0,0 +1,3 @@ +# Installing Icinga DB Web on Debian + + diff --git a/doc/02-Installation.md.d/04-RHEL.md b/doc/02-Installation.md.d/04-RHEL.md new file mode 100644 index 000000000..bf8857619 --- /dev/null +++ b/doc/02-Installation.md.d/04-RHEL.md @@ -0,0 +1,3 @@ +# Installing Icinga DB Web on RHEL + + diff --git a/doc/02-Installation.md.d/05-SLES.md b/doc/02-Installation.md.d/05-SLES.md new file mode 100644 index 000000000..7396fefee --- /dev/null +++ b/doc/02-Installation.md.d/05-SLES.md @@ -0,0 +1,3 @@ +# Installing Icinga DB Web on SLES + + diff --git a/doc/02-Installation.md.d/06-Ubuntu.md b/doc/02-Installation.md.d/06-Ubuntu.md new file mode 100644 index 000000000..9f6f9ff19 --- /dev/null +++ b/doc/02-Installation.md.d/06-Ubuntu.md @@ -0,0 +1,3 @@ +# Installing Icinga DB Web on Ubuntu + + diff --git a/doc/02-Installation.md.d/07-From-Source.md b/doc/02-Installation.md.d/07-From-Source.md new file mode 100644 index 000000000..3fb55f6cd --- /dev/null +++ b/doc/02-Installation.md.d/07-From-Source.md @@ -0,0 +1,3 @@ +# Installing Icinga DB Web from Source + + diff --git a/doc/03-Configuration.md b/doc/03-Configuration.md index 32bd01282..3f807cf8b 100644 --- a/doc/03-Configuration.md +++ b/doc/03-Configuration.md @@ -1,118 +1,63 @@ # Configuration -1. [Database](#database) -2. [Redis](#redis) -3. [Command Transports](#command-transports) -4. [Security](#security) +Icinga DB Web is configured via the web interface. Below you will find an overview of the necessary settings. -## Database +## Database Configuration -If not already done during the installation of Icinga DB Web, setup the Icinga DB database backend now. +Connection configuration for the database to which Icinga DB synchronizes monitoring data. -Create a new [Icinga Web 2 resource](https://icinga.com/docs/icingaweb2/latest/doc/04-Resources/#database) -for [Icinga DB's database](https://icinga.com/docs/icingadb/latest/doc/02-Installation/#configuring-mysql) -using the `Configuration -> Application -> Resources` menu. +1. Create a new resource for the Icinga DB database via the `Configuration → Application → Resources` menu. -Then tell Icinga DB Web which database resource to use. This can be done in -`Configuration -> Modules -> icingadb -> Database`. +2. Configure the resource you just created as the database connection for the Icinga DB Web module using the + `Configuration → Modules → icingadb → Database` menu. -## Redis +## Redis Configuration -To view the most recent state information in Icinga DB Web, make sure to configure the connection details to -[Icinga DB's redis](https://icinga.com/docs/icingadb/latest/doc/02-Installation/#installing-icinga-db-redis) -at `Configuration -> Modules -> icingadb -> Redis`. +Connection configuration for the Redis server where Icinga 2 writes check results. +This data is used to display the latest state information in Icinga DB Web. -### Secondary Master +1. Configure the connection to the Redis server through the `Configuration → Modules → icingadb → Redis` menu. -If you are running a high availability zone with two masters, you can provide the Redis connection details -of the secondary master as well. Icinga DB Web will then use that in case the primary one isn't available. +!!! info -### Using TLS + If you are running a high-availability Icinga 2 setup, + also configure the secondary master's Redis connection details. + Icinga DB Web then uses this connection if the primary one is not available. -If you have setup Redis to only accept encrypted connections, you will need to tell Icinga DB Web the CA certificate -being used for it. This will apply to both connections, the primary and secondary one. +## Command Transport Configuration -#### Authentication +In order to acknowledge problems, force checks, schedule downtimes, etc., +Icinga DB Web needs access to the Icinga 2 API. +For this you need an `ApiUser` object with at least the following permissions on the Icinga 2 side: -It is also possible to authenticate requests over TLS. For this, tell Icinga DB Web which client certificate and -private key to use. +* `actions/*` +* `objects/query/*` +* `objects/modify/*` +* `status/query` -### Manual Configuration +!!! tip -The configuration is stored in two different configuration files. + For single-node setups it is recommended to manage API credentials in the `/etc/icinga2/conf.d/api-users.conf` file. + If you are running a high-availability Icinga 2 setup, please manage the credentials in the master zone. -The TLS configuration is stored in Icinga DB Web's main configuration. It is located at -`/etc/icingaweb2/modules/icingadb/config.ini` by default. In it, the section `redis` -contains the relevant directives. +1. Please add the following Icinga 2 configuration and change the password accordingly: + ``` + object ApiUser "icingadb-web" { + password = "CHANGEME" + permissions = [ "actions/*", "objects/modify/*", "objects/query/*", "status/query" ] + } + ``` +2. Restart Icinga 2 for these changes to take effect. +3. Then configure a command transport for Icinga DB Web + using the credentials you just created via the `Configuration → Modules → icingadb → Command Transports` menu. -The connection configuration is stored in `/etc/icingaweb2/modules/icingadb/redis.ini`. In it, there may be two -sections with the relevant directives: `redis1` and `redis2` +!!! info -#### Example - -**config.ini** -```ini -[redis] -tls = "1" -insecure = "0" -ca = "/var/lib/icingaweb2/modules/icingadb/redis/d37c36724cbf43f204ace4caa5b1b919-ca.pem" -cert = "/var/lib/icingaweb2/modules/icingadb/redis/d5d43b3a1a77227d8c0ee12adc04483c-cert.pem" -key = "/var/lib/icingaweb2/modules/icingadb/redis/f27abcbe23546134a8515283f1987e15-key.pem" -``` - -**redis.ini** -```ini -[redis1] -host = "redis-one" -port = "6380" - -[redis2] -host = "redis-two" -port = "6380" -``` - -## Command Transports - -Command transports are used to perform actions on the Icinga master such as acknowledgements and scheduling downtimes. -(amongst others) - -These can be configured in `Configuration -> Modules -> icingadb -> Command Transports`. - -### Icinga 2 Preparations - -If not already done, [set up Icinga 2's api](https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#setting-up-the-api). -Icinga DB Web requires access to this api, so make sure to create a user with appropriate permissions and ensure it is -reachable by the web server. - -#### Required Permissions - -* actions/* -* objects/query/* -* objects/modify/* - -### Multiple Transports - -You can define multiple command transports. Icinga DB Web will try one transport after another to send a command until -it is successfully sent. - -### Manual Configuration - -The configuration is stored in an INI-file located at `/etc/icingaweb2/modules/icingadb/commandtransports.ini` by -default. In it, every transport starts with a section header containing its name followed by its config directives. - -The section order also defines which transport is used first over another by Icinga DB Web. - -#### Example - -```ini -[icinga2] -transport = "api" -host = "127.0.0.1" ; Icinga 2 host -port = "5665" -username = "icingaweb2" -password = "bea11beb7b810ea9ce6ea" ; Change this! -``` + If you are running a high-availability Icinga 2 setup, + also configure the secondary master's API command transport. + Icinga DB Web then uses this transport if the primary one is not available. ## Security -Setting up permissions and restrictions is covered in its own [chapter](04-Security.md). +To grant users permissions to run commands and restrict them to specific views, +see the [Security](04-Security.md) documentation for the necessary steps. diff --git a/doc/04-Security.md b/doc/04-Security.md index 83305d9bf..c6653d93e 100644 --- a/doc/04-Security.md +++ b/doc/04-Security.md @@ -12,29 +12,29 @@ The same applies to routes, objects and variables. To these, users can be restri > If a role [limits users](#filters) to a specific set of results, the command > permissions or refusals of the very same role only apply to these results. -Name | Allow... ------------------------------------------------|--------------------------------------------------------------- -icingadb/command/* | all commands -icingadb/command/schedule-check | to schedule host and service checks -icingadb/command/schedule-check/active-only | to schedule host and service checks (Only on objects with active checks enabled) -icingadb/command/acknowledge-problem | to acknowledge host and service problems -icingadb/command/remove-acknowledgement | to remove problem acknowledgements -icingadb/command/comment/* | to add and delete host and service comments -icingadb/command/comment/add | to add host and service comments -icingadb/command/comment/delete | to delete host and service comments -icingadb/command/downtime/* | to schedule and delete host and service downtimes -icingadb/command/downtime/schedule | to schedule host and service downtimes -icingadb/command/downtime/delete | to delete host and service downtimes -icingadb/command/process-check-result | to process host and service check results -icingadb/command/feature/instance | to toggle instance-wide features -icingadb/command/feature/object/* | to toggle all features on host and service objects -icingadb/command/feature/object/active-checks | to toggle active checks on host and service objects -icingadb/command/feature/object/passive-checks | to toggle passive checks on host and service objects -icingadb/command/feature/object/notifications | to toggle notifications on host and service objects -icingadb/command/feature/object/event-handler | to toggle event handlers on host and service objects -icingadb/command/feature/object/flap-detection | to toggle flap detection on host and service objects -icingadb/command/send-custom-notification | to send custom notifications for hosts and services -icingadb/object/show-source | to view an object's source data. (May contain sensitive data!) +| Name | Allow... | +|------------------------------------------------|----------------------------------------------------------------------------------| +| icingadb/command/* | all commands | +| icingadb/command/schedule-check | to schedule host and service checks | +| icingadb/command/schedule-check/active-only | to schedule host and service checks (Only on objects with active checks enabled) | +| icingadb/command/acknowledge-problem | to acknowledge host and service problems | +| icingadb/command/remove-acknowledgement | to remove problem acknowledgements | +| icingadb/command/comment/* | to add and delete host and service comments | +| icingadb/command/comment/add | to add host and service comments | +| icingadb/command/comment/delete | to delete host and service comments | +| icingadb/command/downtime/* | to schedule and delete host and service downtimes | +| icingadb/command/downtime/schedule | to schedule host and service downtimes | +| icingadb/command/downtime/delete | to delete host and service downtimes | +| icingadb/command/process-check-result | to process host and service check results | +| icingadb/command/feature/instance | to toggle instance-wide features | +| icingadb/command/feature/object/* | to toggle all features on host and service objects | +| icingadb/command/feature/object/active-checks | to toggle active checks on host and service objects | +| icingadb/command/feature/object/passive-checks | to toggle passive checks on host and service objects | +| icingadb/command/feature/object/notifications | to toggle notifications on host and service objects | +| icingadb/command/feature/object/event-handler | to toggle event handlers on host and service objects | +| icingadb/command/feature/object/flap-detection | to toggle flap detection on host and service objects | +| icingadb/command/send-custom-notification | to send custom notifications for hosts and services | +| icingadb/object/show-source | to view an object's source data. (May contain sensitive data!) | ## Restrictions @@ -46,11 +46,11 @@ Filters limit users to a specific set of results. > > Filters from multiple roles will widen available access. -Name | Description --------------------------|----------------------------------------------------------------------- -icingadb/filter/objects | Restrict access to the Icinga objects that match the filter -icingadb/filter/hosts | Restrict access to the Icinga hosts and services that match the filter -icingadb/filter/services | Restrict access to the Icinga services that match the filter +| Name | Description | +|--------------------------|------------------------------------------------------------------------| +| icingadb/filter/objects | Restrict access to the Icinga objects that match the filter | +| icingadb/filter/hosts | Restrict access to the Icinga hosts and services that match the filter | +| icingadb/filter/services | Restrict access to the Icinga services that match the filter | `icingadb/filter/objects` will only allow users to access matching objects. This applies to all objects, not just hosts or services. It should be one or more [filter expressions](#filter-expressions). @@ -61,25 +61,25 @@ unrestricted. It should be one or more [filter expressions](#filter-expressions) `icingadb/filter/services` will only allow users to access matching services. Other objects remain unrestricted. It should be one or more [filter expressions](#filter-expressions). -### Blacklists +### Denylists -Blacklists prevent users from accessing information and in some cases will block them entirely from it. +Denylists prevent users from accessing information and in some cases will block them entirely from it. > **Note:** > -> Blacklists from multiple roles will further limit access. +> Denylists from multiple roles will further limit access. Name | Description -----------------------------|------------------------------------------------------------------ -icingadb/blacklist/routes | Prevent access to routes that are part of the list -icingadb/blacklist/variables | Hide custom variables of Icinga objects that are part of the list +icingadb/denylist/routes | Prevent access to routes that are part of the list +icingadb/denylist/variables | Hide custom variables of Icinga objects that are part of the list -`icingadb/blacklist/routes` will block users from accessing defined routes and from related information elsewhere. +`icingadb/denylist/routes` will block users from accessing defined routes and from related information elsewhere. For example, if `hostgroups` are part of the list a user won't have access to the hostgroup overview nor to a host's groups shown in its detail area. This should be a comma separated list. Possible values are: hostgroups, servicegroups, contacts, contactgroups -`icingadb/blacklist/variables` will block users from accessing certain custom variables. A user affected by this won't +`icingadb/denylist/variables` will block users from accessing certain custom variables. A user affected by this won't see that those variables even exist. This should be a comma separated list of [variable paths](#variable-paths). It is possible to use [match patterns](#match-patterns). @@ -89,7 +89,7 @@ Protections prevent users from accessing actual data. They will know that there > **Note:** > -> Blacklists from multiple roles will further limit access. +> Denylists from multiple roles will further limit access. Name | Description ---------------------------|----------------------------------------------------------------------------- diff --git a/doc/05-Upgrading.md b/doc/05-Upgrading.md new file mode 100644 index 000000000..7bb3efdd9 --- /dev/null +++ b/doc/05-Upgrading.md @@ -0,0 +1,16 @@ +# Upgrading Icinga DB Web + +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.0 + +**Requirements** + +* You need at least Icinga DB version 1.0.0 to run Icinga DB Web v1.0.0. + +**Configuration Changes** + +* The restrictions `icingadb/blacklist/routes` and `icingadb/blacklist/variables` have been renamed to + `icingadb/denylist/routes` and `icingadb/denylist/variables` respectively. If you use this restriction, + make sure to adjust `/etc/icingaweb2/roles.ini` accordingly. diff --git a/doc/10-Migration.md b/doc/10-Migration.md index d87771280..a7742f3e1 100644 --- a/doc/10-Migration.md +++ b/doc/10-Migration.md @@ -1,10 +1,5 @@ # Migration -1. [Configuration](#configuration) -2. [Dashboards and Navigation](#dashboards-and-navigation) -3. [Restrictions](#restrictions) -4. [Permissions](#permissions) - If you previously used the monitoring module, (built into Icinga Web 2) you may want to migrate your existing configuration, custom dashboards and navigation items as well as permissions or restrictions. @@ -106,19 +101,19 @@ example set of columns conveying the same information shown in the monitoring mo This is now `icingadb/filter/objects` but still accepts the same filter syntax. Only the columns have changed or support for them has been dropped. Check the table below for details: -Old Column Name | New Column Name ----------------------|----------------------- -instance\_name | - -host\_name | host.name -hostgroup\_name | hostgroup.name -service\_description | service.name -servicegroup\_name | servicegroup.name -\_host\_customvar | host.vars.customvar -\_service\_customvar | service.vars.customvar +| Old Column Name | New Column Name | +|----------------------|------------------------| +| instance\_name | - | +| host\_name | host.name | +| hostgroup\_name | hostgroup.name | +| service\_description | service.name | +| servicegroup\_name | servicegroup.name | +| \_host\_customvar | host.vars.customvar | +| \_service\_customvar | service.vars.customvar | ### `monitoring/blacklist/properties` -This is now `icingadb/blacklist/variables`. However, it does not accept the same rules as +This is now `icingadb/denylist/variables`. However, it does not accept the same rules as `monitoring/blacklist/properties`. It still accepts a comma separated list of GLOB like filters, but with some features removed: @@ -133,5 +128,5 @@ Check the [security chapter](04-Security.md#variable-paths) for more details. The command permissions have not changed. It is only the module identifier that has changed of course: `monitoring.command.*` is now `icingadb.command.*` -The `no-monitoring/contacts` permission (or *fake refusal*) is now a restriction: `icingadb/blacklist/routes`. +The `no-monitoring/contacts` permission (or *fake refusal*) is now a restriction: `icingadb/denylist/routes`. Add `users,usergroups` to it to achieve the same effect. diff --git a/doc/res/icingadb-architecture.png b/doc/res/icingadb-architecture.png new file mode 100644 index 000000000..3d55ff757 Binary files /dev/null and b/doc/res/icingadb-architecture.png differ diff --git a/doc/res/icingadb-dashboard.png b/doc/res/icingadb-dashboard.png new file mode 100644 index 000000000..521eb3957 Binary files /dev/null and b/doc/res/icingadb-dashboard.png differ diff --git a/doc/res/icingadb-web.png b/doc/res/icingadb-web.png new file mode 100644 index 000000000..05a3e3185 Binary files /dev/null and b/doc/res/icingadb-web.png differ diff --git a/library/Icingadb/Authentication/ObjectAuthorization.php b/library/Icingadb/Authentication/ObjectAuthorization.php index 15a7f97c1..ba5aa17e4 100644 --- a/library/Icingadb/Authentication/ObjectAuthorization.php +++ b/library/Icingadb/Authentication/ObjectAuthorization.php @@ -120,7 +120,6 @@ public static function matchesOn(string $queryString, Model $object): bool $query ->filter($filter) ->filter(Filter::equal($object->getKeyName(), $uniqueId)) - ->getSelectBase() ->columns([new Expression('1')]); $result = $query->execute()->hasResult(); diff --git a/library/Icingadb/Common/Auth.php b/library/Icingadb/Common/Auth.php index 8329e3e53..c415d62d2 100644 --- a/library/Icingadb/Common/Auth.php +++ b/library/Icingadb/Common/Auth.php @@ -37,11 +37,11 @@ public function isPermittedRoute(string $name): bool } // The empty array is for PHP pre 7.4, older versions require at least a single param for array_merge - $routeBlacklist = array_flip(array_merge([], ...array_map(function ($restriction) { + $routeDenylist = array_flip(array_merge([], ...array_map(function ($restriction) { return StringHelper::trimSplit($restriction); - }, $this->getAuth()->getRestrictions('icingadb/blacklist/routes')))); + }, $this->getAuth()->getRestrictions('icingadb/denylist/routes')))); - return ! array_key_exists($name, $routeBlacklist); + return ! array_key_exists($name, $routeDenylist); } /** @@ -105,7 +105,7 @@ public function isMatchedOn(string $queryString, Model $object): bool * This will apply `icingadb/filter/objects` in any case. `icingadb/filter/services` is only * applied to queries fetching services and `icingadb/filter/hosts` is applied to queries * fetching either hosts or services. It also applies custom variable restrictions and - * obfuscations. (`icingadb/blacklist/variables` and `icingadb/protect/variables`) + * obfuscations. (`icingadb/denylist/variables` and `icingadb/protect/variables`) * * @param Query $query * @@ -145,8 +145,8 @@ public function applyRestrictions(Query $query) $roleFilter = Filter::all(); if ($customVarRelationName !== false) { - if (($restriction = $role->getRestrictions('icingadb/blacklist/variables'))) { - $roleFilter->add($this->parseBlacklist( + if (($restriction = $role->getRestrictions('icingadb/denylist/variables'))) { + $roleFilter->add($this->parseDenylist( $restriction, $customVarRelationName ? $resolver->qualifyColumn('flatname', $customVarRelationName) @@ -155,7 +155,7 @@ public function applyRestrictions(Query $query) } if (($restriction = $role->getRestrictions('icingadb/protect/variables'))) { - $obfuscationRules->add($this->parseBlacklist( + $obfuscationRules->add($this->parseDenylist( $restriction, $customVarRelationName ? $resolver->qualifyColumn('flatname', $customVarRelationName) @@ -316,17 +316,17 @@ function ($k, $v) { } /** - * Parse the given blacklist + * Parse the given denylist * - * @param string $blacklist Comma separated list of column names - * @param string $column The column which should not equal any of the blacklisted names + * @param string $denylist Comma separated list of column names + * @param string $column The column which should not equal any of the denylisted names * * @return Filter\None */ - protected function parseBlacklist(string $blacklist, string $column): Filter\None + protected function parseDenylist(string $denylist, string $column): Filter\None { $filter = Filter::none(); - foreach (explode(',', $blacklist) as $value) { + foreach (explode(',', $denylist) as $value) { $filter->add(Filter::like($column, trim($value))); } diff --git a/library/Icingadb/Common/ObjectInspectionDetail.php b/library/Icingadb/Common/ObjectInspectionDetail.php index a310be7cc..55848516b 100644 --- a/library/Icingadb/Common/ObjectInspectionDetail.php +++ b/library/Icingadb/Common/ObjectInspectionDetail.php @@ -80,7 +80,7 @@ protected function createLastCheckResult() $command = join(' ', array_map('escapeshellarg', $command)); } - $blacklist = [ + $denylist = [ 'command', 'output', 'type', @@ -92,7 +92,7 @@ protected function createLastCheckResult() new HtmlElement('pre', null, Text::create($command)), new HtmlElement('h2', null, Text::create(t('Execution Details'))), $this->createNameValueTable( - array_diff_key($this->attrs['last_check_result'], array_flip($blacklist)), + array_diff_key($this->attrs['last_check_result'], array_flip($denylist)), [ 'execution_end' => [$this, 'formatTimestamp'], 'execution_start' => [$this, 'formatTimestamp'], @@ -126,14 +126,14 @@ protected function createRedisInfo(): array return [$title, sprintf('Failed to decode redis data: %s', $e->getMessage())]; } - $blacklist = [ + $denylist = [ 'commandline', 'environment_id', 'id' ]; return [$title, $this->createNameValueTable( - array_diff_key($data, array_flip($blacklist)), + array_diff_key($data, array_flip($denylist)), [ 'last_state_change' => [$this, 'formatMillisecondTimestamp'], 'last_update' => [$this, 'formatMillisecondTimestamp'], @@ -152,7 +152,7 @@ protected function createRedisInfo(): array protected function createAttributes(): array { - $blacklist = [ + $denylist = [ 'name', '__name', 'host_name', @@ -171,7 +171,7 @@ protected function createAttributes(): array return [ new HtmlElement('h2', null, Text::create(t('Object Attributes'))), $this->createNameValueTable( - array_diff_key($this->attrs, array_flip($blacklist)), + array_diff_key($this->attrs, array_flip($denylist)), [ 'acknowledgement_expiry' => [$this, 'formatTimestamp'], 'acknowledgement_last_change' => [$this, 'formatTimestamp'], diff --git a/library/Icingadb/Compat/CompatHost.php b/library/Icingadb/Compat/CompatHost.php index 73b51dfdf..049457378 100644 --- a/library/Icingadb/Compat/CompatHost.php +++ b/library/Icingadb/Compat/CompatHost.php @@ -42,7 +42,7 @@ class CompatHost extends Host 'host_check_latency' => ['path' => ['state', 'latency']], 'host_check_source' => ['path' => ['state', 'check_source']], 'host_check_timeperiod' => ['path' => ['check_timeperiod_name']], - 'host_current_check_attempt' => ['path' => ['state', 'attempt']], + 'host_current_check_attempt' => ['path' => ['state', 'check_attempt']], 'host_current_notification_number' => null, 'host_event_handler_enabled' => [ 'path' => ['event_handler_enabled'], diff --git a/library/Icingadb/Compat/UrlMigrator.php b/library/Icingadb/Compat/UrlMigrator.php index 1c3b772c1..d3bd839be 100644 --- a/library/Icingadb/Compat/UrlMigrator.php +++ b/library/Icingadb/Compat/UrlMigrator.php @@ -312,7 +312,7 @@ protected static function hostsColumns(): array 'host.check_timeperiod_name' => self::USE_EXPR ], 'host_current_check_attempt' => [ - 'host.state.attempt' => self::USE_EXPR + 'host.state.check_attempt' => self::USE_EXPR ], 'host_current_notification_number' => self::DROP, 'host_display_name' => [ @@ -602,7 +602,7 @@ protected static function servicesColumns(): array ], 'service_active_checks_enabled_changed' => self::DROP, 'service_attempt' => [ - 'service.state.attempt' => self::USE_EXPR + 'service.state.check_attempt' => self::USE_EXPR ], 'service_check_command' => [ 'service.checkcommand_name' => self::USE_EXPR @@ -614,7 +614,7 @@ protected static function servicesColumns(): array 'service.check_timeperiod_name' => self::USE_EXPR ], 'service_current_check_attempt' => [ - 'service.state.attempt' => self::USE_EXPR + 'service.state.check_attempt' => self::USE_EXPR ], 'service_current_notification_number' => self::DROP, 'service_display_name' => [ diff --git a/library/Icingadb/Hook/ActionsHook/ObjectActionsHook.php b/library/Icingadb/Hook/ActionsHook/ObjectActionsHook.php index 696493c85..2f8df33a0 100644 --- a/library/Icingadb/Hook/ActionsHook/ObjectActionsHook.php +++ b/library/Icingadb/Hook/ActionsHook/ObjectActionsHook.php @@ -53,7 +53,7 @@ final public static function loadActions(Model $object): HtmlElement ); } - $list = new HtmlElement('ul', Attributes::create(['class' => 'actions'])); + $list = new HtmlElement('ul', Attributes::create(['class' => 'object-detail-actions'])); foreach (Hook::all($hookName) as $hook) { try { foreach ($hook->getActionsForObject($object) as $link) { diff --git a/library/Icingadb/Model/AcknowledgementHistory.php b/library/Icingadb/Model/AcknowledgementHistory.php index 3e59890c1..409e4b08b 100644 --- a/library/Icingadb/Model/AcknowledgementHistory.php +++ b/library/Icingadb/Model/AcknowledgementHistory.php @@ -51,19 +51,19 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Acknowledgement Environment Id (History)'), - 'endpoint_id' => t('Acknowledgement Endpoint Id (History)'), - 'object_type' => t('Acknowledgement Object Type (History)'), - 'host_id' => t('Acknowledgement Host Id (History)'), - 'service_id' => t('Acknowledgement Service Id (History)'), - 'set_time' => t('Acknowledgement Set Time (History)'), - 'clear_time' => t('Acknowledgement Clear Time (History)'), - 'author' => t('Acknowledgement Author (History)'), - 'cleared_by' => t('Acknowledgement Cleared By (History)'), - 'comment' => t('Acknowledgement Comment (History)'), - 'expire_time' => t('Acknowledgement Expire Time (History)'), - 'is_sticky' => t('Acknowledgement Is Sticky (History)'), - 'is_persistent' => t('Acknowledgement Is Persistent (History)') + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'set_time' => t('Acknowledgement Set Time'), + 'clear_time' => t('Acknowledgement Clear Time'), + 'author' => t('Acknowledgement Author'), + 'cleared_by' => t('Acknowledgement Cleared By'), + 'comment' => t('Acknowledgement Comment'), + 'expire_time' => t('Acknowledgement Expire Time'), + 'is_sticky' => t('Acknowledgement Is Sticky'), + 'is_persistent' => t('Acknowledgement Is Persistent') ]; } diff --git a/library/Icingadb/Model/ActionUrl.php b/library/Icingadb/Model/ActionUrl.php index aab690ee7..e0b092eed 100644 --- a/library/Icingadb/Model/ActionUrl.php +++ b/library/Icingadb/Model/ActionUrl.php @@ -34,7 +34,7 @@ public function getColumnDefinitions() { return [ 'action_url' => t('Action Url'), - 'environment_id' => t('Action Url Environment Id') + 'environment_id' => t('Environment Id') ]; } diff --git a/library/Icingadb/Model/Behavior/BoolCast.php b/library/Icingadb/Model/Behavior/BoolCast.php index 01196d9a1..8ab01ae4b 100644 --- a/library/Icingadb/Model/Behavior/BoolCast.php +++ b/library/Icingadb/Model/Behavior/BoolCast.php @@ -10,7 +10,7 @@ class BoolCast extends PropertyBehavior { public function fromDb($value, $key, $_) { - switch ($value) { + switch ((string) $value) { case 'y': return true; case 'n': diff --git a/library/Icingadb/Model/Checkcommand.php b/library/Icingadb/Model/Checkcommand.php index cddba3220..400a24bd1 100644 --- a/library/Icingadb/Model/Checkcommand.php +++ b/library/Icingadb/Model/Checkcommand.php @@ -39,8 +39,8 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'zone_id' => t('Checkcommand Zone Id'), - 'environment_id' => t('Checkcommand Environment Id'), + 'zone_id' => t('Zone Id'), + 'environment_id' => t('Environment Id'), 'name_checksum' => t('Checkcommand Name Checksum'), 'properties_checksum' => t('Checkcommand Properties Checksum'), 'name' => t('Checkcommand Name'), diff --git a/library/Icingadb/Model/CheckcommandArgument.php b/library/Icingadb/Model/CheckcommandArgument.php index 355679c27..d59d4e3d2 100644 --- a/library/Icingadb/Model/CheckcommandArgument.php +++ b/library/Icingadb/Model/CheckcommandArgument.php @@ -42,18 +42,18 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'checkcommand_id' => t('Checkcommand Argument Command Id'), - 'argument_key' => t('Checkcommand Argument Key'), - 'environment_id' => t('Checkcommand Argument Environment Id'), + 'checkcommand_id' => t('Checkcommand Id'), + 'argument_key' => t('Checkcommand Argument Name'), + 'environment_id' => t('Environment Id'), 'properties_checksum' => t('Checkcommand Argument Properties Checksum'), 'argument_value' => t('Checkcommand Argument Value'), - 'argument_order' => t('Checkcommand Argument Order'), + 'argument_order' => t('Checkcommand Argument Position'), 'description' => t('Checkcommand Argument Description'), - 'argument_key_override' => t('Checkcommand Argument Key Override'), - 'repeat_key' => t('Checkcommand Argument Repeat Key'), + 'argument_key_override' => t('Checkcommand Argument Actual Name'), + 'repeat_key' => t('Checkcommand Argument Repeated'), 'required' => t('Checkcommand Argument Required'), - 'set_if' => t('Checkcommand Argument Set If'), - 'skip_key' => t('Checkcommand Argument Skip Key') + 'set_if' => t('Checkcommand Argument Condition'), + 'skip_key' => t('Checkcommand Argument Without Name') ]; } diff --git a/library/Icingadb/Model/CheckcommandEnvvar.php b/library/Icingadb/Model/CheckcommandEnvvar.php index 5c9fa023e..cbcb92696 100644 --- a/library/Icingadb/Model/CheckcommandEnvvar.php +++ b/library/Icingadb/Model/CheckcommandEnvvar.php @@ -35,9 +35,9 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'checkcommand_id' => t('Checkcommand Envvar Command Id'), - 'envvar_key' => t('Checkcommand Envvar Key'), - 'environment_id' => t('Checkcommand Environment Id'), + 'checkcommand_id' => t('Checkcommand Id'), + 'envvar_key' => t('Checkcommand Envvar Name'), + 'environment_id' => t('Environment Id'), 'properties_checksum' => t('Checkcommand Properties Checksum'), 'envvar_value' => t('Checkcommand Envvar Value') ]; diff --git a/library/Icingadb/Model/Comment.php b/library/Icingadb/Model/Comment.php index 47a560fc9..dd5ee2a0d 100644 --- a/library/Icingadb/Model/Comment.php +++ b/library/Icingadb/Model/Comment.php @@ -48,10 +48,10 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Comment Environment Id'), - 'object_type' => t('Comment Object Type'), - 'host_id' => t('Comment Host Id'), - 'service_id' => t('Comment Service Id'), + 'environment_id' => t('Environment Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), 'name_checksum' => t('Comment Name Checksum'), 'properties_checksum' => t('Comment Properties Checksum'), 'name' => t('Comment Name'), @@ -62,7 +62,7 @@ public function getColumnDefinitions() 'is_persistent' => t('Comment Is Persistent'), 'is_sticky' => t('Comment Is Sticky'), 'expire_time' => t('Comment Expire Time'), - 'zone_id' => t('Comment Zone Id') + 'zone_id' => t('Zone Id') ]; } diff --git a/library/Icingadb/Model/CommentHistory.php b/library/Icingadb/Model/CommentHistory.php index 0fad66970..8428a153e 100644 --- a/library/Icingadb/Model/CommentHistory.php +++ b/library/Icingadb/Model/CommentHistory.php @@ -53,21 +53,21 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Comment Environment Id (History)'), - 'endpoint_id' => t('Comment Endpoint Id (History)'), - 'object_type' => t('Comment Object Type (History)'), - 'host_id' => t('Comment Host Id (History)'), - 'service_id' => t('Comment Service Id (History)'), - 'entry_time' => t('Comment Entry Time (History)'), - 'author' => t('Comment Author (History)'), - 'removed_by' => t('Comment Removed By (History)'), - 'comment' => t('Comment Comment (History)'), - 'entry_type' => t('Comment Entry Type (History)'), - 'is_persistent' => t('Comment Is Persistent (History)'), - 'is_sticky' => t('Comment Is Sticky (History)'), - 'expire_time' => t('Comment Expire Time (History)'), - 'remove_time' => t('Comment Remove Time (History)'), - 'has_been_removed' => t('Comment Has Been Removed (History)') + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'entry_time' => t('Comment Entry Time'), + 'author' => t('Comment Author'), + 'removed_by' => t('Comment Removed By'), + 'comment' => t('Comment Text'), + 'entry_type' => t('Comment Entry Type'), + 'is_persistent' => t('Comment Is Persistent'), + 'is_sticky' => t('Comment Is Sticky'), + 'expire_time' => t('Comment Expire Time'), + 'remove_time' => t('Comment Remove Time'), + 'has_been_removed' => t('Comment Has Been Removed') ]; } diff --git a/library/Icingadb/Model/Downtime.php b/library/Icingadb/Model/Downtime.php index 7f304159d..8fee6d1c6 100644 --- a/library/Icingadb/Model/Downtime.php +++ b/library/Icingadb/Model/Downtime.php @@ -56,12 +56,12 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Downtime Environment Id'), - 'triggered_by_id' => t('Downtime Triggered By Id'), - 'parent_id' => t('Downtime Parent Id'), - 'object_type' => t('Downtime Object Type'), - 'host_id' => t('Downtime Host Id'), - 'service_id' => t('Downtime Service Id'), + 'environment_id' => t('Environment Id'), + 'triggered_by_id' => t('Triggered By Downtime Id'), + 'parent_id' => t('Parent Downtime Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), 'name_checksum' => t('Downtime Name Checksum'), 'properties_checksum' => t('Downtime Properties Checksum'), 'name' => t('Downtime Name'), @@ -77,8 +77,8 @@ public function getColumnDefinitions() 'start_time' => t('Downtime Actual Start'), 'end_time' => t('Downtime Actual End'), 'duration' => t('Downtime Duration'), - 'scheduled_by' => t('Downtime Scheduled By'), - 'zone_id' => t('Downtime Zone Id') + 'scheduled_by' => t('Scheduled By Downtime'), + 'zone_id' => t('Zone Id') ]; } diff --git a/library/Icingadb/Model/DowntimeHistory.php b/library/Icingadb/Model/DowntimeHistory.php index 8fa5616fd..ee4f97373 100644 --- a/library/Icingadb/Model/DowntimeHistory.php +++ b/library/Icingadb/Model/DowntimeHistory.php @@ -58,26 +58,26 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Downtime Environment Id (History)'), - 'endpoint_id' => t('Downtime Endpoint Id (History)'), - 'triggered_by_id' => t('Downtime Triggered By Id (History)'), - 'parent_id' => t('Downtime Parent Id (History)'), - 'object_type' => t('Downtime Object Type (History)'), - 'host_id' => t('Downtime Host Id (History)'), - 'service_id' => t('Downtime Service Id (History)'), - 'entry_time' => t('Downtime Entry Time (History)'), - 'author' => t('Downtime Author (History)'), - 'cancelled_by' => t('Downtime Cancelled By (History)'), - 'comment' => t('Downtime Comment (History)'), - 'is_flexible' => t('Downtime Is Flexible (History)'), - 'flexible_duration' => t('Downtime Flexible Duration (History)'), - 'scheduled_start_time' => t('Downtime Scheduled Start (History)'), - 'scheduled_end_time' => t('Downtime Scheduled End (History)'), - 'start_time' => t('Downtime Actual Start (History)'), - 'end_time' => t('Downtime Actual End (History)'), - 'has_been_cancelled' => t('Downtime Has Been Cancelled (History)'), - 'trigger_time' => t('Downtime Trigger Time (History)'), - 'cancel_time' => t('Downtime Cancel Time (History)') + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'triggered_by_id' => t('Triggered By Downtime Id'), + 'parent_id' => t('Parent Downtime Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'entry_time' => t('Downtime Entry Time'), + 'author' => t('Downtime Author'), + 'cancelled_by' => t('Downtime Cancelled By'), + 'comment' => t('Downtime Comment'), + 'is_flexible' => t('Downtime Is Flexible'), + 'flexible_duration' => t('Downtime Flexible Duration'), + 'scheduled_start_time' => t('Downtime Scheduled Start'), + 'scheduled_end_time' => t('Downtime Scheduled End'), + 'start_time' => t('Downtime Actual Start'), + 'end_time' => t('Downtime Actual End'), + 'has_been_cancelled' => t('Downtime Has Been Cancelled'), + 'trigger_time' => t('Downtime Trigger Time'), + 'cancel_time' => t('Downtime Cancel Time') ]; } diff --git a/library/Icingadb/Model/Endpoint.php b/library/Icingadb/Model/Endpoint.php index 0760f4d8b..257001b74 100644 --- a/library/Icingadb/Model/Endpoint.php +++ b/library/Icingadb/Model/Endpoint.php @@ -36,12 +36,12 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Endpoint Environment Id'), + 'environment_id' => t('Environment Id'), 'name_checksum' => t('Endpoint Name Checksum'), 'properties_checksum' => t('Endpoint Properties Checksum'), 'name' => t('Endpoint Name'), 'name_ci' => t('Endpoint Name (CI)'), - 'zone_id' => t('Endpoint Zone Id') + 'zone_id' => t('Zone Id') ]; } diff --git a/library/Icingadb/Model/Eventcommand.php b/library/Icingadb/Model/Eventcommand.php index 68f1b2312..ad18e2210 100644 --- a/library/Icingadb/Model/Eventcommand.php +++ b/library/Icingadb/Model/Eventcommand.php @@ -39,8 +39,8 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'zone_id' => t('Eventcommand Zone Id'), - 'environment_id' => t('Eventcommand Environment id'), + 'zone_id' => t('Zone Id'), + 'environment_id' => t('Environment Id'), 'name_checksum' => t('Eventcommand Name Checksum'), 'properties_checksum' => t('Eventcommand Properties Checksum'), 'name' => t('Eventcommand Name'), diff --git a/library/Icingadb/Model/EventcommandArgument.php b/library/Icingadb/Model/EventcommandArgument.php index b26945d78..485e5d345 100644 --- a/library/Icingadb/Model/EventcommandArgument.php +++ b/library/Icingadb/Model/EventcommandArgument.php @@ -42,18 +42,18 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'eventcommand_id' => t('Eventcommand Argument Command Id'), - 'argument_key' => t('Eventcommand Argument Key'), - 'environment_id' => t('Eventcommand Argument Environment Id'), + 'eventcommand_id' => t('Eventcommand Id'), + 'argument_key' => t('Eventcommand Argument Name'), + 'environment_id' => t('Environment Id'), 'properties_checksum' => t('Eventcommand Argument Properties Checksum'), 'argument_value' => t('Eventcommand Argument Value'), - 'argument_order' => t('Eventcommand Argument Order'), + 'argument_order' => t('Eventcommand Argument Position'), 'description' => t('Eventcommand Argument Description'), - 'argument_key_override' => t('Eventcommand Argument Key Override'), - 'repeat_key' => t('Eventcommand Argument Repeat Key'), + 'argument_key_override' => t('Eventcommand Argument Actual Name'), + 'repeat_key' => t('Eventcommand Argument Repeated'), 'required' => t('Eventcommand Argument Required'), - 'set_if' => t('Eventcommand Argument Set If'), - 'skip_key' => t('Eventcommand Argument Skip Key') + 'set_if' => t('Eventcommand Argument Condition'), + 'skip_key' => t('Eventcommand Argument Without Name') ]; } diff --git a/library/Icingadb/Model/EventcommandEnvvar.php b/library/Icingadb/Model/EventcommandEnvvar.php index 20fb2f716..3883befcb 100644 --- a/library/Icingadb/Model/EventcommandEnvvar.php +++ b/library/Icingadb/Model/EventcommandEnvvar.php @@ -35,9 +35,9 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'eventcommand_id' => t('Eventcommand Envvar Command Id'), - 'envvar_key' => t('Eventcommand Envvar Key'), - 'environment_id' => t('Eventcommand Envvar Environment Id'), + 'eventcommand_id' => t('Eventcommand Id'), + 'envvar_key' => t('Eventcommand Envvar Name'), + 'environment_id' => t('Environment Id'), 'properties_checksum' => t('Eventcommand Envvar Properties Checksum'), 'envvar_value' => t('Eventcommand Envvar Value') ]; diff --git a/library/Icingadb/Model/FlappingHistory.php b/library/Icingadb/Model/FlappingHistory.php index 99cc2fe6c..377d2cab1 100644 --- a/library/Icingadb/Model/FlappingHistory.php +++ b/library/Icingadb/Model/FlappingHistory.php @@ -48,17 +48,17 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Flapping Environment Id (History)'), - 'endpoint_id' => t('Flapping Endpoint Id (History)'), - 'object_type' => t('Flapping Object Type (History)'), - 'host_id' => t('Flapping Host Id (History)'), - 'service_id' => t('Flapping Service Id (History)'), - 'start_time' => t('Flapping Start Time (History)'), - 'end_time' => t('Flapping End Time (History)'), - 'percent_state_change_start' => t('Flapping Percent State Change Start (History)'), - 'percent_state_change_end' => t('Flapping Percent State Change End (History)'), - 'flapping_threshold_low' => t('Flapping Threshold Low (History)'), - 'flapping_threshold_high' => t('Flapping Threshold High (History)') + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'start_time' => t('Flapping Start Time'), + 'end_time' => t('Flapping End Time'), + 'percent_state_change_start' => t('Flapping Percent State Change Start'), + 'percent_state_change_end' => t('Flapping Percent State Change End'), + 'flapping_threshold_low' => t('Flapping Threshold Low'), + 'flapping_threshold_high' => t('Flapping Threshold High') ]; } diff --git a/library/Icingadb/Model/History.php b/library/Icingadb/Model/History.php index 01ff74d20..e5b4dd6e8 100644 --- a/library/Icingadb/Model/History.php +++ b/library/Icingadb/Model/History.php @@ -51,11 +51,11 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Environment Id (History)'), - 'endpoint_id' => t('Endpoint Id (History)'), - 'object_type' => t('Event Object Type'), - 'host_id' => t('Host Id (History)'), - 'service_id' => t('Service Id (History)'), + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), 'event_type' => t('Event Type'), 'event_time' => t('Event Time') ]; diff --git a/library/Icingadb/Model/Host.php b/library/Icingadb/Model/Host.php index d3890d6eb..110f86c24 100644 --- a/library/Icingadb/Model/Host.php +++ b/library/Icingadb/Model/Host.php @@ -78,7 +78,7 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Host Environment Id'), + 'environment_id' => t('Environment Id'), 'name_checksum' => t('Host Name Checksum'), 'properties_checksum' => t('Host Properties Checksum'), 'name' => t('Host Name'), @@ -88,11 +88,11 @@ public function getColumnDefinitions() 'address6' => t('Host Address (IPv6)'), 'address_bin' => t('Host Address (IPv4, Binary)'), 'address6_bin' => t('Host Address (IPv6, Binary)'), - 'checkcommand_name' => t('Host Checkcommand'), - 'checkcommand_id' => t('Host Checkcommand Id'), + 'checkcommand_name' => t('Checkcommand Name'), + 'checkcommand_id' => t('Checkcommand Id'), 'max_check_attempts' => t('Host Max Check Attempts'), - 'check_timeperiod_name' => t('Host Check Timeperiod'), - 'check_timeperiod_id' => t('Host Check Timeperiod Id'), + 'check_timeperiod_name' => t('Check Timeperiod Name'), + 'check_timeperiod_id' => t('Check Timeperiod Id'), 'check_timeout' => t('Host Check Timeout'), 'check_interval' => t('Host Check Interval'), 'check_retry_interval' => t('Host Check Retry Inverval'), @@ -104,18 +104,18 @@ public function getColumnDefinitions() 'flapping_threshold_low' => t('Host Flapping Threshold Low'), 'flapping_threshold_high' => t('Host Flapping Threshold High'), 'perfdata_enabled' => t('Host Performance Data Enabled'), - 'eventcommand_name' => t('Host Eventcommand'), - 'eventcommand_id' => t('Host Eventcommand Id'), + 'eventcommand_name' => t('Eventcommand Name'), + 'eventcommand_id' => t('Eventcommand Id'), 'is_volatile' => t('Host Is Volatile'), - 'action_url_id' => t('Host Action Url Id'), - 'notes_url_id' => t('Host Notes Url Id'), + 'action_url_id' => t('Action Url Id'), + 'notes_url_id' => t('Notes Url Id'), 'notes' => t('Host Notes'), - 'icon_image_id' => t('Host Icon Image Id'), - 'icon_image_alt' => t('Host Icon Image Alt'), - 'zone_name' => t('Host Zone'), - 'zone_id' => t('Host Zone Id'), - 'command_endpoint_name' => t('Host Command Endpoint'), - 'command_endpoint_id' => t('Host Command Endpoint Id') + 'icon_image_id' => t('Icon Image Id'), + 'icon_image_alt' => t('Icon Image Alt'), + 'zone_name' => t('Zone Name'), + 'zone_id' => t('Zone Id'), + 'command_endpoint_name' => t('Endpoint Name'), + 'command_endpoint_id' => t('Endpoint Id') ]; } diff --git a/library/Icingadb/Model/HostState.php b/library/Icingadb/Model/HostState.php index 11953d840..0c8341717 100644 --- a/library/Icingadb/Model/HostState.php +++ b/library/Icingadb/Model/HostState.php @@ -25,35 +25,35 @@ public function getKeyName() public function getColumnDefinitions() { return [ - 'environment_id' => t('Host State Environment Id'), + 'environment_id' => t('Environment Id'), 'state_type' => t('Host State Type'), 'soft_state' => t('Host Soft State'), 'hard_state' => t('Host Hard State'), 'previous_soft_state' => t('Host Previous Soft State'), 'previous_hard_state' => t('Host Previous Hard State'), - 'attempt' => t('Host State Attempt No.'), + 'check_attempt' => t('Host Check Attempt No.'), 'severity' => t('Host State Severity'), - 'output' => t('Host State Output'), - 'long_output' => t('Host State Long Output'), - 'performance_data' => t('Host State Performance Data'), - 'normalized_performance_data' => t('Host State Normalized Performance Data'), - 'check_commandline' => t('Host State Check Commandline'), - 'is_problem' => t('Host State Is Problem'), - 'is_handled' => t('Host State Is Handled'), - 'is_reachable' => t('Host State Is Reachable'), - 'is_flapping' => t('Host State Is Flapping'), - 'is_overdue' => t('Host State Is Overdue'), - 'is_acknowledged' => t('Host State Is Acknowledged'), - 'acknowledgement_comment_id' => t('Host State Acknowledgement Comment Id'), - 'in_downtime' => t('Host State In Downtime'), - 'execution_time' => t('Host State Execution Time'), - 'latency' => t('Host State Latency'), - 'timeout' => t('Host State Timeout'), - 'check_source' => t('Host State Check Source'), - 'last_update' => t('Host State Last Update'), - 'last_state_change' => t('Host State Last State Change'), - 'next_check' => t('Host State Next Check'), - 'next_update' => t('Host State Next Update') + 'output' => t('Host Output'), + 'long_output' => t('Host Long Output'), + 'performance_data' => t('Host Performance Data'), + 'normalized_performance_data' => t('Host Normalized Performance Data'), + 'check_commandline' => t('Host Check Commandline'), + 'is_problem' => t('Host Has Problem'), + 'is_handled' => t('Host Is Handled'), + 'is_reachable' => t('Host Is Reachable'), + 'is_flapping' => t('Host Is Flapping'), + 'is_overdue' => t('Host Check Is Overdue'), + 'is_acknowledged' => t('Host Is Acknowledged'), + 'acknowledgement_comment_id' => t('Acknowledgement Comment Id'), + 'in_downtime' => t('Host In Downtime'), + 'execution_time' => t('Host Check Execution Time'), + 'latency' => t('Host Check Latency'), + 'check_timeout' => t('Host Check Timeout'), + 'check_source' => t('Host Check Source'), + 'last_update' => t('Host Last Update'), + 'last_state_change' => t('Host Last State Change'), + 'next_check' => t('Host Next Check'), + 'next_update' => t('Host Next Update') ]; } diff --git a/library/Icingadb/Model/Hostgroup.php b/library/Icingadb/Model/Hostgroup.php index ae543e24b..1dfae3129 100644 --- a/library/Icingadb/Model/Hostgroup.php +++ b/library/Icingadb/Model/Hostgroup.php @@ -38,13 +38,13 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Hostgroup Environment Id'), + 'environment_id' => t('Environment Id'), 'name_checksum' => t('Hostgroup Name Checksum'), 'properties_checksum' => t('Hostgroup Properties Checksum'), 'name' => t('Hostgroup Name'), 'name_ci' => t('Hostgroup Name (CI)'), 'display_name' => t('Hostgroup Display Name'), - 'zone_id' => t('Hostgroup Zone Id') + 'zone_id' => t('Zone Id') ]; } diff --git a/library/Icingadb/Model/IconImage.php b/library/Icingadb/Model/IconImage.php index 55eb4b1cc..212234a9f 100644 --- a/library/Icingadb/Model/IconImage.php +++ b/library/Icingadb/Model/IconImage.php @@ -33,7 +33,7 @@ public function getColumnDefinitions() { return [ 'icon_image' => t('Icon Image'), - 'environment_id' => t('Icon Image Environment Id') + 'environment_id' => t('Environment Id') ]; } diff --git a/library/Icingadb/Model/NotesUrl.php b/library/Icingadb/Model/NotesUrl.php index 821c091da..5865c524f 100644 --- a/library/Icingadb/Model/NotesUrl.php +++ b/library/Icingadb/Model/NotesUrl.php @@ -34,7 +34,7 @@ public function getColumnDefinitions() { return [ 'notes_url' => t('Notes Url'), - 'environment_id' => t('Notes Url Environment Id') + 'environment_id' => t('Environment Id') ]; } diff --git a/library/Icingadb/Model/Notification.php b/library/Icingadb/Model/Notification.php index d35b88d83..8d423013a 100644 --- a/library/Icingadb/Model/Notification.php +++ b/library/Icingadb/Model/Notification.php @@ -47,21 +47,21 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Notification Environment Id'), + 'environment_id' => t('Environment Id'), 'name_checksum' => t('Notification Name Checksum'), 'properties_checksum' => t('Notification Properties Checksum'), 'name' => t('Notification Name'), 'name_ci' => t('Notification Name (CI)'), - 'host_id' => t('Notification Host Id'), - 'service_id' => t('Notification Service Id'), - 'notificationcommand_id' => t('Notification Command Id'), - 'times_begin' => t('Notification Times Begin'), - 'times_end' => t('Notification Times End'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'notificationcommand_id' => t('Notificationcommand Id'), + 'times_begin' => t('Notification Escalate After'), + 'times_end' => t('Notification Escalate Until'), 'notification_interval' => t('Notification Interval'), - 'timeperiod_id' => t('Notification Timeperiod Id'), - 'states' => t('Notification States'), - 'types' => t('Notification Types'), - 'zone_id' => t('Notification Zone Id') + 'timeperiod_id' => t('Timeperiod Id'), + 'states' => t('Notification State Filter'), + 'types' => t('Notification Type Filter'), + 'zone_id' => t('Zone Id') ]; } diff --git a/library/Icingadb/Model/NotificationHistory.php b/library/Icingadb/Model/NotificationHistory.php index b7fc69c6d..eb0637678 100644 --- a/library/Icingadb/Model/NotificationHistory.php +++ b/library/Icingadb/Model/NotificationHistory.php @@ -51,20 +51,20 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'id' => t('Notification History Id'), - 'environment_id' => t('Notification Environment Id (History)'), - 'endpoint_id' => t('Notification Endpoint Id (History)'), - 'object_type' => t('Notification Object Type (History)'), - 'host_id' => t('Notification Host Id (History)'), - 'service_id' => t('Notification Service Id (History)'), - 'notification_id' => t('Notification Id (History)'), - 'type' => t('Notification Type (History)'), - 'send_time' => t('Notification Sent On (History)'), - 'state' => t('Notification Object State (History)'), - 'previous_hard_state' => t('Notification Previous Object State (History)'), - 'author' => t('Notification Author (History)'), - 'text' => t('Notification Text (History)'), - 'users_notified' => t('Notification Users Notified (History)') + 'id' => t('History Id'), + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'notification_id' => t('Notification Id'), + 'type' => t('Notification Type'), + 'send_time' => t('Notification Sent On'), + 'state' => t('Hard State'), + 'previous_hard_state' => t('Previous Hard State'), + 'author' => t('Notification Author'), + 'text' => t('Notification Text'), + 'users_notified' => t('Users Notified') ]; } diff --git a/library/Icingadb/Model/Notificationcommand.php b/library/Icingadb/Model/Notificationcommand.php index 9507f679a..6ee2a217b 100644 --- a/library/Icingadb/Model/Notificationcommand.php +++ b/library/Icingadb/Model/Notificationcommand.php @@ -39,8 +39,8 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'zone_id' => t('Notificationcommand Zone Id'), - 'environment_id' => t('Notificationcommand Environment Id'), + 'zone_id' => t('Zone Id'), + 'environment_id' => t('Environment Id'), 'name_checksum' => t('Notificationcommand Name Checksum'), 'properties_checksum' => t('Notificationcommand Properties Checksum'), 'name' => t('Notificationcommand Name'), diff --git a/library/Icingadb/Model/NotificationcommandArgument.php b/library/Icingadb/Model/NotificationcommandArgument.php index f5f031e87..e8550226b 100644 --- a/library/Icingadb/Model/NotificationcommandArgument.php +++ b/library/Icingadb/Model/NotificationcommandArgument.php @@ -42,18 +42,18 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'notificationcommand_id' => t('Notificationcommand Argument Command Id'), - 'argument_key' => t('Notificationcommand Argument Key'), - 'environment_id' => t('Notificationcommand Argument Environment Id'), + 'notificationcommand_id' => t('Notificationcommand Id'), + 'argument_key' => t('Notificationcommand Argument Name'), + 'environment_id' => t('Environment Id'), 'properties_checksum' => t('Notificationcommand Argument Properties Checksum'), 'argument_value' => t('Notificationcommand Argument Value'), - 'argument_order' => t('Notificationcommand Argument Order'), + 'argument_order' => t('Notificationcommand Argument Position'), 'description' => t('Notificationcommand Argument Description'), - 'argument_key_override' => t('Notificationcommand Argument Key Override'), - 'repeat_key' => t('Notificationcommand Argument Repeat Key'), + 'argument_key_override' => t('Notificationcommand Argument Actual Name'), + 'repeat_key' => t('Notificationcommand Argument Repeated'), 'required' => t('Notificationcommand Argument Required'), - 'set_if' => t('Notificationcommand Argument Set If'), - 'skip_key' => t('Notificationcommand Argument Skip Key') + 'set_if' => t('Notificationcommand Argument Condition'), + 'skip_key' => t('Notificationcommand Argument Without Name') ]; } diff --git a/library/Icingadb/Model/NotificationcommandEnvvar.php b/library/Icingadb/Model/NotificationcommandEnvvar.php index 2d4327b4c..09f77b0cc 100644 --- a/library/Icingadb/Model/NotificationcommandEnvvar.php +++ b/library/Icingadb/Model/NotificationcommandEnvvar.php @@ -35,9 +35,9 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'notificationcommand_id' => t('Notificationcommand Envvar Command Id'), + 'notificationcommand_id' => t('Notificationcommand Id'), 'envvar_key' => t('Notificationcommand Envvar Key'), - 'environment_id' => t('Notificationcommand Envvar Environment Id'), + 'environment_id' => t('Environment Id'), 'properties_checksum' => t('Notificationcommand Envvar Properties Checksum'), 'envvar_value' => t('Notificationcommand Envvar Value') ]; diff --git a/library/Icingadb/Model/Service.php b/library/Icingadb/Model/Service.php index b2bb75b28..0ef47aae1 100644 --- a/library/Icingadb/Model/Service.php +++ b/library/Icingadb/Model/Service.php @@ -72,18 +72,18 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Service Environment Id'), + 'environment_id' => t('Environment Id'), 'name_checksum' => t('Service Name Checksum'), 'properties_checksum' => t('Service Properties Checksum'), - 'host_id' => t('Service Host Id'), + 'host_id' => t('Host Id'), 'name' => t('Service Name'), 'name_ci' => t('Service Name (CI)'), 'display_name' => t('Service Display Name'), - 'checkcommand_name' => t('Service Checkcommand'), - 'checkcommand_id' => t('Service Checkcommand Id'), + 'checkcommand_name' => t('Checkcommand Name'), + 'checkcommand_id' => t('Checkcommand Id'), 'max_check_attempts' => t('Service Max Check Attempts'), - 'check_timeperiod_name' => t('Service Check Timeperiod'), - 'check_timeperiod_id' => t('Service Check Timeperiod Id'), + 'check_timeperiod_name' => t('Check Timeperiod Name'), + 'check_timeperiod_id' => t('Check Timeperiod Id'), 'check_timeout' => t('Service Check Timeout'), 'check_interval' => t('Service Check Interval'), 'check_retry_interval' => t('Service Check Retry Inverval'), @@ -95,18 +95,18 @@ public function getColumnDefinitions() 'flapping_threshold_low' => t('Service Flapping Threshold Low'), 'flapping_threshold_high' => t('Service Flapping Threshold High'), 'perfdata_enabled' => t('Service Performance Data Enabled'), - 'eventcommand_name' => t('Service Eventcommand'), - 'eventcommand_id' => t('Service Eventcommand Id'), + 'eventcommand_name' => t('Eventcommand Name'), + 'eventcommand_id' => t('Eventcommand Id'), 'is_volatile' => t('Service Is Volatile'), - 'action_url_id' => t('Service Action Url Id'), - 'notes_url_id' => t('Service Notes Url Id'), + 'action_url_id' => t('Action Url Id'), + 'notes_url_id' => t('Notes Url Id'), 'notes' => t('Service Notes'), - 'icon_image_id' => t('Service Icon Image Id'), - 'icon_image_alt' => t('Service Icon Image Alt'), - 'zone_name' => t('Service Zone'), - 'zone_id' => t('Service Zone Id'), - 'command_endpoint_name' => t('Service Command Endpoint'), - 'command_endpoint_id' => t('Service Command Endpoint Id') + 'icon_image_id' => t('Icon Image Id'), + 'icon_image_alt' => t('Icon Image Alt'), + 'zone_name' => t('Zone Name'), + 'zone_id' => t('Zone Id'), + 'command_endpoint_name' => t('Endpoint Name'), + 'command_endpoint_id' => t('Endpoint Id') ]; } diff --git a/library/Icingadb/Model/ServiceState.php b/library/Icingadb/Model/ServiceState.php index 868a92eaa..9de2a21e1 100644 --- a/library/Icingadb/Model/ServiceState.php +++ b/library/Icingadb/Model/ServiceState.php @@ -22,35 +22,35 @@ public function getKeyName() public function getColumnDefinitions() { return [ - 'environment_id' => t('Service State Environment Id'), + 'environment_id' => t('Environment Id'), 'state_type' => t('Service State Type'), 'soft_state' => t('Service Soft State'), 'hard_state' => t('Service Hard State'), 'previous_soft_state' => t('Service Previous Soft State'), 'previous_hard_state' => t('Service Previous Hard State'), - 'attempt' => t('Service State Attempt No.'), + 'check_attempt' => t('Service Check Attempt No.'), 'severity' => t('Service State Severity'), - 'output' => t('Service State Output'), - 'long_output' => t('Service State Long Output'), - 'performance_data' => t('Service State Performance Data'), - 'normalized_performance_data' => t('Service State Normalized Performance Data'), - 'check_commandline' => t('Service State Check Commandline'), - 'is_problem' => t('Service State Is Problem'), - 'is_handled' => t('Service State Is Handled'), - 'is_reachable' => t('Service State Is Reachable'), - 'is_flapping' => t('Service State Is Flapping'), - 'is_overdue' => t('Service State Is Overdue'), - 'is_acknowledged' => t('Service State Is Acknowledged'), - 'acknowledgement_comment_id' => t('Service State Acknowledgement Comment Id'), - 'in_downtime' => t('Service State In Downtime'), - 'execution_time' => t('Service State Execution Time'), - 'latency' => t('Service State Latency'), - 'timeout' => t('Service State Timeout'), - 'check_source' => t('Service State Check Source'), - 'last_update' => t('Service State Last Update'), - 'last_state_change' => t('Service State Last State Change'), - 'next_check' => t('Service State Next Check'), - 'next_update' => t('Service State Next Update') + 'output' => t('Service Output'), + 'long_output' => t('Service Long Output'), + 'performance_data' => t('Service Performance Data'), + 'normalized_performance_data' => t('Service Normalized Performance Data'), + 'check_commandline' => t('Service Check Commandline'), + 'is_problem' => t('Service Has Problem'), + 'is_handled' => t('Service Is Handled'), + 'is_reachable' => t('Service Is Reachable'), + 'is_flapping' => t('Service Is Flapping'), + 'is_overdue' => t('Service Check Is Overdue'), + 'is_acknowledged' => t('Service Is Acknowledged'), + 'acknowledgement_comment_id' => t('Acknowledgement Comment Id'), + 'in_downtime' => t('Service In Downtime'), + 'execution_time' => t('Service Check Execution Time'), + 'latency' => t('Service Check Latency'), + 'check_timeout' => t('Service Check Timeout'), + 'check_source' => t('Service Check Source'), + 'last_update' => t('Service Last Update'), + 'last_state_change' => t('Service Last State Change'), + 'next_check' => t('Service Next Check'), + 'next_update' => t('Service Next Update') ]; } diff --git a/library/Icingadb/Model/Servicegroup.php b/library/Icingadb/Model/Servicegroup.php index 0e6f134b9..34f67bd76 100644 --- a/library/Icingadb/Model/Servicegroup.php +++ b/library/Icingadb/Model/Servicegroup.php @@ -38,13 +38,13 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Servicegroup Environment Id'), + 'environment_id' => t('Environment Id'), 'name_checksum' => t('Servicegroup Name Checksum'), 'properties_checksum' => t('Servicegroup Properties Checksum'), 'name' => t('Servicegroup Name'), 'name_ci' => t('Servicegroup Name (CI)'), 'display_name' => t('Servicegroup Display Name'), - 'zone_id' => t('Servicegroup Zone Id') + 'zone_id' => t('Zone Id') ]; } diff --git a/library/Icingadb/Model/State.php b/library/Icingadb/Model/State.php index 5000b9a78..acd376931 100644 --- a/library/Icingadb/Model/State.php +++ b/library/Icingadb/Model/State.php @@ -24,7 +24,7 @@ public function getColumns() 'hard_state', 'previous_soft_state', 'previous_hard_state', - 'attempt', + 'check_attempt', 'severity', 'output', 'long_output', @@ -42,7 +42,7 @@ public function getColumns() 'in_downtime', 'execution_time', 'latency', - 'timeout', + 'check_timeout', 'check_source', 'scheduling_source', 'last_update', diff --git a/library/Icingadb/Model/StateHistory.php b/library/Icingadb/Model/StateHistory.php index bc19ac353..a4ae3d3f7 100644 --- a/library/Icingadb/Model/StateHistory.php +++ b/library/Icingadb/Model/StateHistory.php @@ -40,7 +40,7 @@ public function getColumns() 'state_type', 'soft_state', 'hard_state', - 'attempt', + 'check_attempt', 'previous_soft_state', 'previous_hard_state', 'output', @@ -54,22 +54,22 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('State Environment Id (History)'), - 'endpoint_id' => t('State Endpoint Id (History)'), - 'object_type' => t('State Object Type (History)'), - 'host_id' => t('State Host Id (History)'), - 'service_id' => t('State Service Id (History)'), - 'event_time' => t('State Event Time (History)'), - 'state_type' => t('State Type (History)'), - 'soft_state' => t('Soft State (History)'), - 'hard_state' => t('Hard State (History)'), - 'attempt' => t('State Attempt No. (History)'), - 'previous_soft_state' => t('Previous Soft State (History)'), - 'previous_hard_state' => t('Previous Hard State (History)'), - 'output' => t('State Output (History)'), - 'long_output' => t('State Long Output (History)'), - 'max_check_attempts' => t('State Max Check Attempts (History)'), - 'check_source' => t('State Check Source (History)') + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'event_time' => t('Event Time'), + 'state_type' => t('Event State Type'), + 'soft_state' => t('Event Soft State'), + 'hard_state' => t('Event Hard State'), + 'check_attempt' => t('Event Check Attempt No.'), + 'previous_soft_state' => t('Event Previous Soft State'), + 'previous_hard_state' => t('Event Previous Hard State'), + 'output' => t('Event Output'), + 'long_output' => t('Event Long Output'), + 'max_check_attempts' => t('Event Max Check Attempts'), + 'check_source' => t('Event Check Source') ]; } diff --git a/library/Icingadb/Model/Timeperiod.php b/library/Icingadb/Model/Timeperiod.php index 1da6073d4..26dd72222 100644 --- a/library/Icingadb/Model/Timeperiod.php +++ b/library/Icingadb/Model/Timeperiod.php @@ -39,14 +39,14 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Timeperiod Environment Id'), + 'environment_id' => t('Environment Id'), 'name_checksum' => t('Timeperiod Name Checksum'), 'properties_checksum' => t('Timeperiod Properties Checksum'), 'name' => t('Timeperiod Name'), 'name_ci' => t('Timeperiod Name (CI)'), 'display_name' => t('Timeperiod Display Name'), 'prefer_includes' => t('Timeperiod Prefer Includes'), - 'zone_id' => t('Timeperiod Zone Id') + 'zone_id' => t('Zone Id') ]; } diff --git a/library/Icingadb/Model/TimeperiodRange.php b/library/Icingadb/Model/TimeperiodRange.php index 8eb4c8ec2..62e87f8cf 100644 --- a/library/Icingadb/Model/TimeperiodRange.php +++ b/library/Icingadb/Model/TimeperiodRange.php @@ -34,10 +34,10 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'timeperiod_id' => t('Timeperiod Range Period Id'), - 'range_key' => t('Timeperiod Range Key'), - 'environment_id' => t('Timeperiod Range Environment Id'), - 'range_value' => t('Timeperiod Range Value') + 'timeperiod_id' => t('Timeperiod Id'), + 'range_key' => t('Timeperiod Range Date(s)/Day'), + 'environment_id' => t('Environment Id'), + 'range_value' => t('Timeperiod Range Time') ]; } diff --git a/library/Icingadb/Model/User.php b/library/Icingadb/Model/User.php index dc81ed263..e894e0fc9 100644 --- a/library/Icingadb/Model/User.php +++ b/library/Icingadb/Model/User.php @@ -45,7 +45,7 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('User Environment Id'), + 'environment_id' => t('Environment Id'), 'name_checksum' => t('User Name Checksum'), 'properties_checksum' => t('User Properties Checksum'), 'name' => t('User Name'), @@ -54,10 +54,10 @@ public function getColumnDefinitions() 'email' => t('User Email'), 'pager' => t('User Pager'), 'notifications_enabled' => t('User Receives Notifications'), - 'timeperiod_id' => t('User Timeperiod Id'), - 'states' => t('User States'), - 'types' => t('User Types'), - 'zone_id' => t('User Zone Id') + 'timeperiod_id' => t('Timeperiod Id'), + 'states' => t('Notification State Filter'), + 'types' => t('Notification Type Filter'), + 'zone_id' => t('Zone Id') ]; } diff --git a/library/Icingadb/Model/Usergroup.php b/library/Icingadb/Model/Usergroup.php index 3e96cc3cb..703477088 100644 --- a/library/Icingadb/Model/Usergroup.php +++ b/library/Icingadb/Model/Usergroup.php @@ -38,13 +38,13 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Usergroup Environment Id'), + 'environment_id' => t('Environment Id'), 'name_checksum' => t('Usergroup Name Checksum'), 'properties_checksum' => t('Usergroup Properties Checksum'), 'name' => t('Usergroup Name'), 'name_ci' => t('Usergroup Name (CI)'), 'display_name' => t('Usergroup Display Name'), - 'zone_id' => t('Usergroup Zone Id') + 'zone_id' => t('Zone Id') ]; } diff --git a/library/Icingadb/Model/Zone.php b/library/Icingadb/Model/Zone.php index 96d08b8c2..aaf3bbfd3 100644 --- a/library/Icingadb/Model/Zone.php +++ b/library/Icingadb/Model/Zone.php @@ -38,13 +38,13 @@ public function getColumns() public function getColumnDefinitions() { return [ - 'environment_id' => t('Zone Environment Id'), + 'environment_id' => t('Environment Id'), 'name_checksum' => t('Zone Name Checksum'), 'properties_checksum' => t('Zone Properties Checksum'), 'name' => t('Zone Name'), 'name_ci' => t('Zone Name (CI)'), 'is_global' => t('Zone Is Global'), - 'parent_id' => t('Zone Parent Id'), + 'parent_id' => t('Parent Zone Id'), 'depth' => t('Zone Depth') ]; } diff --git a/library/Icingadb/ProvidedHook/ApplicationState.php b/library/Icingadb/ProvidedHook/ApplicationState.php index f05fa6320..1b6f8c1db 100644 --- a/library/Icingadb/ProvidedHook/ApplicationState.php +++ b/library/Icingadb/ProvidedHook/ApplicationState.php @@ -18,6 +18,25 @@ class ApplicationState extends ApplicationStateHook public function collectMessages() { + try { + $lastIcingaHeartbeat = IcingaRedis::getLastIcingaHeartbeat(); + } catch (Exception $e) { + $downSince = Session::getSession()->getNamespace('icingadb')->get('redis.down-since'); + + if ($downSince === null) { + $downSince = time(); + Session::getSession()->getNamespace('icingadb')->set('redis.down-since', $downSince); + } + + $this->addError( + 'icingadb/redis-down', + $downSince, + sprintf(t("Can't connect to Icinga Redis: %s"), $e->getMessage()) + ); + + return; + } + $instance = Instance::on($this->getDb()) ->with(['endpoint']) ->filter(Filter::equal('responsible', true)) @@ -50,59 +69,43 @@ public function collectMessages() $outdatedDbHeartbeat = $instance->heartbeat < time() - 60; - try { - $lastIcingaHeartbeat = IcingaRedis::getLastIcingaHeartbeat(); - if ($lastIcingaHeartbeat === null) { - $missingSince = Session::getSession() - ->getNamespace('icingadb')->get('redis.heartbeat-missing-since'); - - if ($missingSince === null) { - $missingSince = time(); - Session::getSession() - ->getNamespace('icingadb')->set('redis.heartbeat-missing-since', $missingSince); - } - - $lastIcingaHeartbeat = $missingSince; - } else { - Session::getSession()->getNamespace('icingadb')->delete('redis.heartbeat-missing-since'); - } + if ($lastIcingaHeartbeat === null) { + $missingSince = Session::getSession() + ->getNamespace('icingadb')->get('redis.heartbeat-missing-since'); - switch (true) { - case $outdatedDbHeartbeat && $instance->heartbeat > $lastIcingaHeartbeat: - $this->addError( - 'icingadb/redis-outdated', - $lastIcingaHeartbeat, - t('Icinga Redis is outdated. Make sure Icinga 2 is running and connected to Redis.') - ); - - break; - case $outdatedDbHeartbeat: - $this->addError( - 'icingadb/icingadb-down', - $instance->heartbeat, - t( - 'It seems that Icinga DB is not running.' - . ' Make sure Icinga DB is running and writing into the database.' - ) - ); - - break; + if ($missingSince === null) { + $missingSince = time(); + Session::getSession() + ->getNamespace('icingadb')->set('redis.heartbeat-missing-since', $missingSince); } - Session::getSession()->getNamespace('icingadb')->delete('redis.down-since'); - } catch (Exception $e) { - $downSince = Session::getSession()->getNamespace('icingadb')->get('redis.down-since'); - - if ($downSince === null) { - $downSince = time(); - Session::getSession()->getNamespace('icingadb')->set('redis.down-since', $downSince); - } + $lastIcingaHeartbeat = $missingSince; + } else { + Session::getSession()->getNamespace('icingadb')->delete('redis.heartbeat-missing-since'); + } - $this->addError( - 'icingadb/redis-down', - $downSince, - sprintf(t("Can't connect to Icinga Redis: %s"), $e->getMessage()) - ); + switch (true) { + case $outdatedDbHeartbeat && $instance->heartbeat > $lastIcingaHeartbeat: + $this->addError( + 'icingadb/redis-outdated', + $lastIcingaHeartbeat, + t('Icinga Redis is outdated. Make sure Icinga 2 is running and connected to Redis.') + ); + + break; + case $outdatedDbHeartbeat: + $this->addError( + 'icingadb/icingadb-down', + $instance->heartbeat, + t( + 'It seems that Icinga DB is not running.' + . ' Make sure Icinga DB is running and writing into the database.' + ) + ); + + break; } + + Session::getSession()->getNamespace('icingadb')->delete('redis.down-since'); } } diff --git a/library/Icingadb/ProvidedHook/RedisHealth.php b/library/Icingadb/ProvidedHook/RedisHealth.php index b4b83d8cb..9e71154fc 100644 --- a/library/Icingadb/ProvidedHook/RedisHealth.php +++ b/library/Icingadb/ProvidedHook/RedisHealth.php @@ -48,7 +48,7 @@ public function checkHealth() $this->setMessage(t('Icinga Redis outdated. Make sure Icinga 2 is running and connected to Redis.')); } } catch (Exception $e) { - $this->setState(self::STATE_UNKNOWN); + $this->setState(self::STATE_CRITICAL); $this->setMessage(sprintf(t("Can't connect to Icinga Redis: %s"), $e->getMessage())); } } diff --git a/library/Icingadb/Redis/VolatileState.php b/library/Icingadb/Redis/VolatileState.php deleted file mode 100644 index d15b00a3e..000000000 --- a/library/Icingadb/Redis/VolatileState.php +++ /dev/null @@ -1,65 +0,0 @@ -redis = $redis; - } - - /** - * Fetch volatile state - * - * @param State $state - * - * @return $this - */ - public function fetch(State $state): self - { - $type = substr($state->getTableName(), 0, -6); - - $json = $this->redis->hGet("icinga:{$type}:state", bin2hex($state->{$type . '_id'})); - if ($json !== null) { - $data = json_decode($json, true); - $data = array_intersect_key($data, array_flip(static::$keys)); - - $state->setProperties($data); - } - - return $this; - } -} diff --git a/library/Icingadb/Redis/VolatileStateResults.php b/library/Icingadb/Redis/VolatileStateResults.php index 5ad1d4045..186022a30 100644 --- a/library/Icingadb/Redis/VolatileStateResults.php +++ b/library/Icingadb/Redis/VolatileStateResults.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Icingadb\Redis; +use Exception; use Generator; use Icinga\Application\Benchmark; use Icinga\Module\Icingadb\Common\IcingaRedis; @@ -12,6 +13,7 @@ use ipl\Orm\Query; use ipl\Orm\Resolver; use ipl\Orm\ResultSet; +use Predis\Client; use RuntimeException; class VolatileStateResults extends ResultSet @@ -19,6 +21,9 @@ class VolatileStateResults extends ResultSet /** @var Resolver */ private $resolver; + /** @var Client */ + private $redis; + /** @var bool Whether Redis updates were applied */ private $updatesApplied = false; @@ -27,12 +32,28 @@ public static function fromQuery(Query $query) $self = parent::fromQuery($query); $self->resolver = $query->getResolver(); + try { + $self->redis = IcingaRedis::instance()->getConnection(); + } catch (Exception $e) { + // The error has already been logged + } + return $self; } + /** + * Get whether Redis is unavailable + * + * @return bool + */ + public function isRedisUnavailable(): bool + { + return $this->redis === null; + } + public function current() { - if (! $this->updatesApplied && ! $this->isCacheDisabled) { + if ($this->redis && ! $this->updatesApplied && ! $this->isCacheDisabled) { $this->rewind(); } @@ -41,7 +62,7 @@ public function current() public function key(): int { - if (! $this->updatesApplied && ! $this->isCacheDisabled) { + if ($this->redis && ! $this->updatesApplied && ! $this->isCacheDisabled) { $this->rewind(); } @@ -50,7 +71,7 @@ public function key(): int public function rewind(): void { - if (! $this->updatesApplied && ! $this->isCacheDisabled) { + if ($this->redis && ! $this->updatesApplied && ! $this->isCacheDisabled) { $this->updatesApplied = true; $this->advance(); @@ -67,6 +88,9 @@ protected function applyRedisUpdates() $type = null; $behaviors = null; + $keys = []; + $hostStateKeys = []; + $states = []; $hostStates = []; foreach ($this as $row) { @@ -86,8 +110,15 @@ protected function applyRedisUpdates() } $states[bin2hex($row->id)] = $row->state; + if (empty($keys)) { + $keys = $row->state->getColumns(); + } + if ($type === 'service' && $row->host instanceof Host) { $hostStates[bin2hex($row->host->id)] = $row->host->state; + if (empty($hostStateKeys)) { + $hostStateKeys = $row->host->state->getColumns(); + } } } @@ -95,7 +126,7 @@ protected function applyRedisUpdates() return; } - foreach ($this->fetchStates("icinga:{$type}:state", array_keys($states)) as $id => $data) { + foreach ($this->fetchStates("icinga:{$type}:state", array_keys($states), $keys) as $id => $data) { foreach ($data as $key => $value) { $data[$key] = $behaviors->retrieveProperty($value, $key); } @@ -104,7 +135,7 @@ protected function applyRedisUpdates() } if ($type === 'service' && ! empty($hostStates)) { - foreach ($this->fetchStates('icinga:host:state', array_keys($hostStates)) as $id => $data) { + foreach ($this->fetchStates('icinga:host:state', array_keys($hostStates), $hostStateKeys) as $id => $data) { foreach ($data as $key => $value) { $data[$key] = $behaviors->retrieveProperty($value, $key); } @@ -114,15 +145,19 @@ protected function applyRedisUpdates() } } - protected function fetchStates(string $key, array $ids): Generator + protected function fetchStates(string $key, array $ids, array $keys): Generator { - $results = IcingaRedis::instance()->getConnection()->hmget($key, $ids); + $results = $this->redis->hmget($key, $ids); foreach ($results as $i => $json) { if ($json !== null) { $data = json_decode($json, true); - $data = array_intersect_key($data, array_flip(VolatileState::$keys)); + $keyMap = array_fill_keys($keys, null); + unset($keyMap['is_overdue']); // Is calculated by Icinga DB, not Icinga 2, hence it's never in redis + + // TODO: Remove once https://github.com/Icinga/icinga2/issues/9427 is fixed + $data['state_type'] = $data['state_type'] === 0 ? 'soft' : 'hard'; - yield $ids[$i] => $data; + yield $ids[$i] => array_intersect_key(array_merge($keyMap, $data), $keyMap); } } } diff --git a/library/Icingadb/Web/Control/SearchBar/ObjectSuggestions.php b/library/Icingadb/Web/Control/SearchBar/ObjectSuggestions.php index c7b1f2513..b1a9491ae 100644 --- a/library/Icingadb/Web/Control/SearchBar/ObjectSuggestions.php +++ b/library/Icingadb/Web/Control/SearchBar/ObjectSuggestions.php @@ -91,6 +91,29 @@ public function getModel(): Model return $this->model; } + protected function shouldShowRelationFor(string $column): bool + { + if (strpos($column, '.vars.') !== false) { + return false; + } + + $tableName = $this->getModel()->getTableName(); + $columnPath = explode('.', $column); + + switch (count($columnPath)) { + case 3: + if ($columnPath[1] !== 'state' || ! in_array($tableName, ['host', 'service'])) { + return true; + } + + // For host/service state relation columns apply the same rules + case 2: + return $columnPath[0] !== $tableName; + default: + return true; + } + } + protected function createQuickSearchFilter($searchTerm) { $model = $this->getModel(); @@ -219,7 +242,7 @@ protected function fetchColumnSuggestions($searchTerm) protected function matchSuggestion($path, $label, $searchTerm) { - if (preg_match('/_(?>id|bin|checksum)$/', $path)) { + if (preg_match('/[_.](id|bin|checksum)$/', $path)) { // Only suggest exotic columns if the user knows about them $trimmedSearch = trim($searchTerm, ' *'); return substr($path, -strlen($trimmedSearch)) === $trimmedSearch; @@ -296,9 +319,9 @@ public static function collectFilterColumns(Model $model, Resolver $resolver): G self::collectRelations($resolver, $model, $models, []); } - foreach ($models as $path => $model) { - /** @var Model $model */ - foreach ($resolver->getColumnDefinitions($model) as $columnName => $definition) { + foreach ($models as $path => $targetModel) { + /** @var Model $targetModel */ + foreach ($resolver->getColumnDefinitions($targetModel) as $columnName => $definition) { yield $path . '.' . $columnName => $definition->getLabel(); } } @@ -325,22 +348,22 @@ public static function collectFilterColumns(Model $model, Resolver $resolver): G $foreignMetaDataSources = []; if (! $model instanceof Host) { - $foreignMetaDataSources[] = ['host.user', ' (' . t('Host') . ')']; - $foreignMetaDataSources[] = ['host.usergroup', ' (' . t('Host') . ')']; + $foreignMetaDataSources[] = 'host.user'; + $foreignMetaDataSources[] = 'host.usergroup'; } if (! $model instanceof Service) { - $foreignMetaDataSources[] = ['service.user', ' (' . t('Service') . ')']; - $foreignMetaDataSources[] = ['service.usergroup', ' (' . t('Service') . ')']; + $foreignMetaDataSources[] = 'service.user'; + $foreignMetaDataSources[] = 'service.usergroup'; } - foreach ($foreignMetaDataSources as list($path, $suffix)) { + foreach ($foreignMetaDataSources as $path) { $foreignColumnDefinitions = $resolver->getColumnDefinitions($resolver->resolveRelation( $resolver->qualifyPath($path, $model->getTableName()), $model )->getTarget()); foreach ($foreignColumnDefinitions as $columnName => $columnDefinition) { - yield "$path.$columnName" => $columnDefinition->getLabel() . $suffix; + yield "$path.$columnName" => $columnDefinition->getLabel(); } } } @@ -361,7 +384,7 @@ protected static function collectRelations(Resolver $resolver, Model $subject, a foreach ($resolver->getRelations($subject) as $name => $relation) { /** @var Relation $relation */ $isHasOne = $relation instanceof HasOne; - if (empty($path) || $isHasOne) { + if (empty($path) || $name === 'state' || $name === 'last_comment') { $relationPath = [$name]; if ($isHasOne && empty($path)) { array_unshift($relationPath, $subject->getTableName()); diff --git a/library/Icingadb/Widget/Detail/CheckStatistics.php b/library/Icingadb/Widget/Detail/CheckStatistics.php index 54d9cd942..51bcb6384 100644 --- a/library/Icingadb/Widget/Detail/CheckStatistics.php +++ b/library/Icingadb/Widget/Detail/CheckStatistics.php @@ -6,6 +6,7 @@ use Icinga\Date\DateFormatter; use Icinga\Module\Icingadb\Widget\CheckAttempt; +use Icinga\Module\Icingadb\Widget\EmptyState; use Icinga\Util\Format; use ipl\Html\BaseHtmlElement; use ipl\Html\Html; @@ -122,7 +123,12 @@ protected function assembleBody(BaseHtmlElement $body) $interval = Html::tag( 'li', ['class' => 'interval'], - new VerticalKeyValue('Interval', Format::seconds($this->object->check_interval)) + new VerticalKeyValue( + t('Interval'), + $this->object->check_interval + ? Format::seconds($this->object->check_interval) + : (new EmptyState(t('n. a.')))->setTag('span') + ) ); $nextCheck = Html::tag( 'li', @@ -157,29 +163,42 @@ protected function assembleBody(BaseHtmlElement $body) protected function assembleFooter(BaseHtmlElement $footer) { - $footer->add(new HorizontalKeyValue(t('Scheduling Source') . ':', $this->object->state->scheduling_source)); + $footer->add(new HorizontalKeyValue( + t('Scheduling Source') . ':', + $this->object->state->scheduling_source ?? (new EmptyState(t('n. a.')))->setTag('span') + )); } protected function assembleHeader(BaseHtmlElement $header) { - $checkSource = [ - new StateBall($this->object->state->is_reachable ? 'up' : 'down', StateBall::SIZE_MEDIUM), - ' ', - $this->object->state->check_source - ]; + $checkSource = (new EmptyState(t('n. a.')))->setTag('span'); + if ($this->object->state->check_source) { + $checkSource = [ + new StateBall($this->object->state->is_reachable ? 'up' : 'down', StateBall::SIZE_MEDIUM), + ' ', + $this->object->state->check_source + ]; + } $header->add([ new VerticalKeyValue(t('Command'), $this->object->checkcommand_name), new VerticalKeyValue( t('Attempts'), - new CheckAttempt((int) $this->object->state->attempt, (int) $this->object->max_check_attempts) + new CheckAttempt((int) $this->object->state->check_attempt, (int) $this->object->max_check_attempts) ), new VerticalKeyValue(t('Check Source'), $checkSource), new VerticalKeyValue( t('Execution time'), - Format::seconds($this->object->state->execution_time) + $this->object->state->execution_time + ? Format::seconds($this->object->state->execution_time) + : (new EmptyState(t('n. a.')))->setTag('span') ), - new VerticalKeyValue(t('Latency'), Format::seconds($this->object->state->latency)) + new VerticalKeyValue( + t('Latency'), + $this->object->state->latency + ? Format::seconds($this->object->state->latency) + : (new EmptyState(t('n. a.')))->setTag('span') + ) ]); } } diff --git a/library/Icingadb/Widget/Detail/EventDetail.php b/library/Icingadb/Widget/Detail/EventDetail.php index 4c50a2c0e..78d3c0b7f 100644 --- a/library/Icingadb/Widget/Detail/EventDetail.php +++ b/library/Icingadb/Widget/Detail/EventDetail.php @@ -216,7 +216,7 @@ protected function assembleStateChangeEvent(StateHistory $stateChange) if ($stateChange->state_type === 'soft') { $eventInfo[] = new HorizontalKeyValue(t('Check Attempt'), sprintf( t('%d of %d'), - $stateChange->attempt, + $stateChange->check_attempt, $stateChange->max_check_attempts )); } diff --git a/library/Icingadb/Widget/Detail/ObjectDetail.php b/library/Icingadb/Widget/Detail/ObjectDetail.php index 7a74e7abd..d206bc251 100644 --- a/library/Icingadb/Widget/Detail/ObjectDetail.php +++ b/library/Icingadb/Widget/Detail/ObjectDetail.php @@ -169,7 +169,7 @@ protected function createActions() return [ Html::tag('h2', t('Actions')), - new HtmlString($navigation->getRenderer()->setCssClass('actions')->render()), + new HtmlString($navigation->getRenderer()->setCssClass('object-detail-actions')->render()), $moduleActions->isEmpty() ? null : $moduleActions ]; } @@ -331,7 +331,7 @@ protected function createNotes() $content = []; if (! $navigation->isEmpty() && $navigation->hasRenderableItems()) { - $content[] = new HtmlString($navigation->getRenderer()->setCssClass('actions')->render()); + $content[] = new HtmlString($navigation->getRenderer()->setCssClass('object-detail-actions')->render()); } if ($notes !== '') { diff --git a/library/Icingadb/Widget/Detail/ObjectsDetail.php b/library/Icingadb/Widget/Detail/ObjectsDetail.php index 18b55667c..f30823a3b 100644 --- a/library/Icingadb/Widget/Detail/ObjectsDetail.php +++ b/library/Icingadb/Widget/Detail/ObjectsDetail.php @@ -72,7 +72,7 @@ protected function createChart(): BaseHtmlElement tp('Host', 'Hosts', $this->summary->hosts_total), $this->summary->hosts_total ), - new HostStateBadges($badges) + $badges ]); } else { $servicesChart = (new Donut()) diff --git a/library/Icingadb/Widget/Detail/PerfDataTable.php b/library/Icingadb/Widget/Detail/PerfDataTable.php index 0a01b2d25..0dc3db03b 100644 --- a/library/Icingadb/Widget/Detail/PerfDataTable.php +++ b/library/Icingadb/Widget/Detail/PerfDataTable.php @@ -52,6 +52,14 @@ public function assemble() uasort( $pieChartData, function ($a, $b) { + if ($a->isVisualizable() && ! $b->isVisualizable()) { + return -1; + } elseif (! $a->isVisualizable() && $b->isVisualizable()) { + return 1; + } elseif (! $a->isVisualizable() && ! $b->isVisualizable()) { + return 0; + } + return $a->worseThan($b) ? -1 : ($b->worseThan($a) ? 1 : 0); } ); diff --git a/library/Icingadb/Widget/Detail/QuickActions.php b/library/Icingadb/Widget/Detail/QuickActions.php index 2ea26c26a..dc3049329 100644 --- a/library/Icingadb/Widget/Detail/QuickActions.php +++ b/library/Icingadb/Widget/Detail/QuickActions.php @@ -11,8 +11,10 @@ use Icinga\Module\Icingadb\Forms\Command\Object\RemoveAcknowledgementForm; use Icinga\Module\Icingadb\Model\Host; use Icinga\Module\Icingadb\Model\Service; +use Icinga\Web\Widget\Flyout; use ipl\Html\BaseHtmlElement; use ipl\Html\Html; +use ipl\Html\HtmlElement; use ipl\Web\Widget\Icon; class QuickActions extends BaseHtmlElement @@ -22,13 +24,16 @@ class QuickActions extends BaseHtmlElement /** @var Host|Service */ protected $object; - protected $tag = 'ul'; + protected $tag = 'div'; protected $defaultAttributes = ['class' => 'quick-actions']; + protected $menu; + public function __construct($object) { $this->object = $object; + $this->menu = HtmlElement::create('ul', ['class' => 'nav flyout-menu']); } protected function assemble() @@ -40,7 +45,7 @@ protected function assemble() ->setAction($this->getLink('removeAcknowledgement')) ->setObjects([$this->object]); - $this->add(Html::tag('li', $removeAckForm)); + $this->menu->addHtml(Html::tag('li', $removeAckForm)); } } elseif ($this->isGrantedOn('icingadb/command/acknowledge-problem', $this->object)) { $this->assembleAction( @@ -59,7 +64,11 @@ protected function assemble() && $this->isGrantedOn('icingadb/command/schedule-check/active-only', $this->object) ) ) { - $this->add(Html::tag('li', (new CheckNowForm())->setAction($this->getLink('checkNow')))); + $this->menu->addHtml(Html::tag( + 'li', + ['class' => 'has-icon'], + (new CheckNowForm())->setAction($this->getLink('checkNow')) + )); } if ($this->isGrantedOn('icingadb/command/comment/add', $this->object)) { @@ -115,6 +124,12 @@ protected function assemble() ) ); } + + + $flyout = new Flyout(HtmlElement::create('button', null, new Icon('bars')), true); + $flyout->addHtml($this->menu); + + $this->addHtml($flyout); } protected function assembleAction(string $action, string $label, string $icon, string $title) @@ -134,7 +149,7 @@ protected function assembleAction(string $action, string $label, string $icon, s ] ); - $this->add(Html::tag('li', $link)); + $this->menu->addHtml(Html::tag('li', ['class' => 'has-icon'], $link)); } protected function getLink($action) diff --git a/library/Icingadb/Widget/ItemList/BaseCommentListItem.php b/library/Icingadb/Widget/ItemList/BaseCommentListItem.php index 2f77dff63..1a3135439 100644 --- a/library/Icingadb/Widget/ItemList/BaseCommentListItem.php +++ b/library/Icingadb/Widget/ItemList/BaseCommentListItem.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Icingadb\Widget\ItemList; +use ipl\Html\Html; use Icinga\Module\Icingadb\Common\HostLink; use Icinga\Module\Icingadb\Common\Icons; use Icinga\Module\Icingadb\Common\Links; @@ -13,6 +14,7 @@ use Icinga\Module\Icingadb\Common\ServiceLink; use Icinga\Module\Icingadb\Model\Comment; use Icinga\Module\Icingadb\Common\BaseListItem; +use ipl\Html\FormattedString; use ipl\Web\Widget\TimeAgo; use ipl\Html\Attributes; use ipl\Html\BaseHtmlElement; @@ -21,6 +23,7 @@ use ipl\Stdlib\Filter; use ipl\Web\Widget\Icon; use ipl\Web\Widget\Link; +use ipl\Web\Widget\TimeUntil; /** * Comment item of a comment list. Represents one database row. @@ -101,7 +104,17 @@ protected function assembleVisual(BaseHtmlElement $visual) protected function createTimestamp() { - return new TimeAgo($this->item->entry_time); + if ($this->item->expire_time) { + return Html::tag( + 'span', + FormattedString::create(t("expires %s"), new TimeUntil($this->item->expire_time)) + ); + } + + return Html::tag( + 'span', + FormattedString::create(t("created %s"), new TimeAgo($this->item->entry_time)) + ); } protected function init() diff --git a/library/Icingadb/Widget/ItemList/BaseHistoryListItem.php b/library/Icingadb/Widget/ItemList/BaseHistoryListItem.php index 4de477c99..e643eba02 100644 --- a/library/Icingadb/Widget/ItemList/BaseHistoryListItem.php +++ b/library/Icingadb/Widget/ItemList/BaseHistoryListItem.php @@ -78,7 +78,7 @@ protected function assembleCaption(BaseHtmlElement $caption) ->add(sprintf( t('State Change Rate: %.2f%%; Start Threshold: %.2f%%'), $this->item->flapping->percent_state_change_start, - $this->item->host->flapping_threshold_high + $this->item->flapping->flapping_threshold_high )) ->getAttributes() ->add('class', 'plugin-output'); @@ -88,8 +88,8 @@ protected function assembleCaption(BaseHtmlElement $caption) $caption ->add(sprintf( t('State Change Rate: %.2f%%; End Threshold: %.2f%%; Flapping for %s'), - $this->item->host->flapping_threshold_low, - $this->item->host->flapping_threshold_high, + $this->item->flapping->percent_state_change_end, + $this->item->flapping->flapping_threshold_low, DateFormatter::formatDuration( $this->item->flapping->end_time - $this->item->flapping->start_time ) @@ -203,7 +203,7 @@ protected function assembleVisual(BaseHtmlElement $visual) } $visual->addHtml(new CheckAttempt( - (int) $this->item->state->attempt, + (int) $this->item->state->check_attempt, (int) $this->item->state->max_check_attempts )); } else { diff --git a/library/Icingadb/Widget/ItemList/StateList.php b/library/Icingadb/Widget/ItemList/StateList.php index 471fb4fd1..cf6ec0b86 100644 --- a/library/Icingadb/Widget/ItemList/StateList.php +++ b/library/Icingadb/Widget/ItemList/StateList.php @@ -7,6 +7,9 @@ use Icinga\Module\Icingadb\Common\BaseItemList; use Icinga\Module\Icingadb\Common\NoSubjectLink; use Icinga\Module\Icingadb\Common\ViewMode; +use Icinga\Module\Icingadb\Redis\VolatileStateResults; +use Icinga\Module\Icingadb\Widget\Notice; +use ipl\Html\HtmlDocument; abstract class StateList extends BaseItemList { @@ -18,5 +21,11 @@ protected function assemble() $this->addAttributes(['class' => $this->getViewMode()]); parent::assemble(); + + if ($this->data instanceof VolatileStateResults && $this->data->isRedisUnavailable()) { + $this->prependWrapper((new HtmlDocument())->addHtml(new Notice( + t('Icinga Redis is currently unavailable. The shown information might be outdated.') + ))); + } } } diff --git a/library/Icingadb/Widget/ItemList/StateListItem.php b/library/Icingadb/Widget/ItemList/StateListItem.php index 2434e4bc2..865b35adb 100644 --- a/library/Icingadb/Widget/ItemList/StateListItem.php +++ b/library/Icingadb/Widget/ItemList/StateListItem.php @@ -84,7 +84,9 @@ protected function assembleVisual(BaseHtmlElement $visual) $visual->addHtml($stateBall); if ($this->state->state_type === 'soft') { - $visual->addHtml(new CheckAttempt((int) $this->state->attempt, (int) $this->item->max_check_attempts)); + $visual->addHtml( + new CheckAttempt((int) $this->state->check_attempt, (int) $this->item->max_check_attempts) + ); } } diff --git a/library/Icingadb/Widget/ItemTable/StateRowItem.php b/library/Icingadb/Widget/ItemTable/StateRowItem.php index 369c3f0e3..6e2cb5cf0 100644 --- a/library/Icingadb/Widget/ItemTable/StateRowItem.php +++ b/library/Icingadb/Widget/ItemTable/StateRowItem.php @@ -55,7 +55,7 @@ protected function assembleVisual(BaseHtmlElement $visual) $visual->addHtml($stateBall); if ($this->item->state->state_type === 'soft') { $visual->addHtml(new CheckAttempt( - (int) $this->item->state->attempt, + (int) $this->item->state->check_attempt, (int) $this->item->max_check_attempts )); } diff --git a/library/Icingadb/Widget/Notice.php b/library/Icingadb/Widget/Notice.php new file mode 100644 index 000000000..998ad30d3 --- /dev/null +++ b/library/Icingadb/Widget/Notice.php @@ -0,0 +1,31 @@ + 'notice']; + + public function __construct($content) + { + $this->content = $content; + } + + protected function assemble() + { + $this->addHtml(new Icon('triangle-exclamation')); + $this->addHtml((new HtmlElement('span'))->add($this->content)); + $this->addHtml(new Icon('triangle-exclamation')); + } +} diff --git a/module.info b/module.info index c4e497f7f..fc0c47f0a 100644 --- a/module.info +++ b/module.info @@ -1,5 +1,5 @@ Module: icingadb -Version: 1.0.0-rc2 +Version: 1.0.0 Requires: Libraries: icinga-php-library (>=0.9.0), icinga-php-thirdparty (>=0.11.0) Description: Icinga DB Web diff --git a/public/css/common.less b/public/css/common.less index b89a161b5..3047ed01c 100644 --- a/public/css/common.less +++ b/public/css/common.less @@ -84,7 +84,7 @@ div.show-more { .box-shadow(0, 0, 0, 1px, @gray-lighter); flex-shrink: 0; position: relative; // Required for the host meta info control - z-index: 1; // The content may clip, this ensures the separator is always visible + z-index: 2; // The content may clip, this ensures the separator is always visible > :not(:only-child) { margin-bottom: .5em; @@ -185,6 +185,10 @@ div.show-more { .show-more { margin-top: .25em; } + + .notice { + display: none; + } } .content > h2:first-child, diff --git a/public/css/widget/actions.less b/public/css/widget/actions.less index f6bf7750b..796fc38cc 100644 --- a/public/css/widget/actions.less +++ b/public/css/widget/actions.less @@ -1,4 +1,4 @@ -.actions a { +.object-detail-actions a { border-bottom: 1px solid @gray-light; display: inline-block; margin-bottom: .25em; @@ -13,7 +13,7 @@ } } -ul.actions { +ul.object-detail-actions { list-style-type: none; padding: 0; margin: 0; diff --git a/public/css/widget/notice.less b/public/css/widget/notice.less new file mode 100644 index 000000000..706766564 --- /dev/null +++ b/public/css/widget/notice.less @@ -0,0 +1,23 @@ +// Style + +.notice { + @margin: 1em / 1.25; + @padding: .75em / 1.25; + + .rounded-corners(); + padding: @padding; + color: @text-color-on-icinga-blue; + background-color: @state-warning; + font-weight: bold; + font-size: 1.25em; + + // Layout + display: flex; + align-items: baseline; + justify-content: space-between; + margin: 0 @margin @margin @margin; + + > span { + .text-ellipsis(); + } +} diff --git a/public/css/widget/performance-data-table.less b/public/css/widget/performance-data-table.less index 0582aa400..a1a7b6ee7 100644 --- a/public/css/widget/performance-data-table.less +++ b/public/css/widget/performance-data-table.less @@ -2,7 +2,7 @@ .performance-data-table { width: 100%; - overflow: auto; + overflow-x: auto; display: block; tr:not(:last-child) { diff --git a/public/css/widget/quick-actions.less b/public/css/widget/quick-actions.less index e41398178..574df8eba 100644 --- a/public/css/widget/quick-actions.less +++ b/public/css/widget/quick-actions.less @@ -1,9 +1,11 @@ .quick-actions { - display: flex; - flex-wrap: wrap; - list-style-type: none; - margin: 0 -.5em; - padding: 0; + .flyout-menu { + display: flex; + flex-wrap: wrap; + list-style-type: none; + margin: 0 -.5em; + padding: 0; + } a { text-decoration: none; @@ -33,14 +35,45 @@ } #layout.twocols:not(.wide-layout) { - .quick-actions { + .quick-actions .flyout-menu { justify-content: space-between; - min-width: 100%; } } -#layout.wide-layout .controls { - .quick-actions { - float: left; +#layout.minimal-layout .quick-actions { + > button { + display: block; + position: fixed; + bottom: ~"calc(env(safe-area-inset-bottom) + 4.5em)"; + right: 1em; + padding: 0 1em; + background: @icinga-blue; + color: @text-color-on-icinga-blue; + box-shadow: 0 0 1em 0 rgba(0,0,0,.25); + line-height: 3.5; + .appearance(none); + .rounded-corners(50%); + border: none; + + .icon { + font-size: 1.5em; + + &:before { + margin-right: 0; + } + } + } + + .flyout { + bottom: ~"calc(env(safe-area-inset-bottom) + 7.5em)"; + top: auto; + position: fixed; + right: 1em; + left: 1em; + + // Caret + &:before { + right: 1.125em; + } } }