From 5dd85a7ee1b188de55f00dd107f3fa7ba2211fd8 Mon Sep 17 00:00:00 2001 From: Marius Hein Date: Fri, 9 May 2014 13:25:16 +0200 Subject: [PATCH 01/55] Vagrant: Add Icinga2 and test configuration refs #6127 --- .../files/etc/icinga2/conf.d/commands.conf | 48 ++ .../files/etc/icinga2/conf.d/test-config.conf | 681 ++++++++++++++++++ .../icinga2/features-available/ido-mysql.conf | 13 + .../icinga2/features-available/ido-pgsql.conf | 13 + .../modules/monitoring/instances.ini | 2 +- .../files/etc/icingaweb/resources.ini | 6 +- .vagrant-puppet/manifests/default.pp | 120 ++- 7 files changed, 868 insertions(+), 15 deletions(-) create mode 100644 .vagrant-puppet/files/etc/icinga2/conf.d/commands.conf create mode 100644 .vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf create mode 100644 .vagrant-puppet/files/etc/icinga2/features-available/ido-mysql.conf create mode 100644 .vagrant-puppet/files/etc/icinga2/features-available/ido-pgsql.conf diff --git a/.vagrant-puppet/files/etc/icinga2/conf.d/commands.conf b/.vagrant-puppet/files/etc/icinga2/conf.d/commands.conf new file mode 100644 index 000000000..9000ac090 --- /dev/null +++ b/.vagrant-puppet/files/etc/icinga2/conf.d/commands.conf @@ -0,0 +1,48 @@ +/* Command objects */ + +object CheckCommand "kernel" { + import "plugin-check-command" + + command = [ "sudo", SysconfDir + "/icinga2/scripts/check_kernel" ] +} + +object NotificationCommand "mail-host-notification" { + import "plugin-notification-command" + + command = [ "/bin/true" ] + + env = { + "NOTIFICATIONTYPE" = "$notification.type$" + "HOSTALIAS" = "$host.display_name$", + "HOSTADDRESS" = "$address$", + "HOSTSTATE" = "$host.state$", + "LONGDATETIME" = "$icinga.long_date_time$", + "HOSTOUTPUT" = "$host.output$", + "NOTIFICATIONAUTHORNAME" = "$notification.author$", + "NOTIFICATIONCOMMENT" = "$notification.comment$", + "HOSTDISPLAYNAME" = "$host.display_name$", + "USEREMAIL" = "$user.email$" + } +} + +object NotificationCommand "mail-service-notification" { + import "plugin-notification-command" + + command = [ "/bin/true" ] + + env = { + "NOTIFICATIONTYPE" = "$notification.type$" + "SERVICEDESC" = "$service.name$" + "HOSTALIAS" = "$host.display_name$", + "HOSTADDRESS" = "$address$", + "SERVICESTATE" = "$service.state$", + "LONGDATETIME" = "$icinga.long_date_time$", + "SERVICEOUTPUT" = "$service.output$", + "NOTIFICATIONAUTHORNAME" = "$notification.author$", + "NOTIFICATIONCOMMENT" = "$notification.comment$", + "HOSTDISPLAYNAME" = "$host.display_name$", + "SERVICEDISPLAYNAME" = "$service.display_name$", + "USEREMAIL" = "$user.email$" + } +} + diff --git a/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf b/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf new file mode 100644 index 000000000..279f2ec1a --- /dev/null +++ b/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf @@ -0,0 +1,681 @@ + +template CheckCommand "dummy-host-generic" { + import "plugin-check-command" + command = [ PluginDir + "/libexec/test_hostcheck.pl" ] + arguments = { + "--type" = "$check_type$" + "--failchance" = "$check_failchance$" + "--previous-state" = "$check_previous_state$" + "--state-duration" = "$check_state_duration$" + "--hostname" = "$check_hostname$" + } + + vars.check_type = "UP" + vars.check_failchance = "2%" + vars.check_previous_state = "$state$" + vars.check_state_duration = "$duration_sec$" + vars.check_hostname = "$name$" +} + +template CheckCommand "dummy-service-generic" { + import "plugin-check-command" + command = [ PluginDir + "/libexec/test_servicecheck.pl" ] + arguments = { + "--total-critical-on-host" = "$check_critical_on_host$" + "--total-warning-on-host" = "$check_warning_on_host$" + "--type" = "$check_type$" + "--failchance" = "$check_failchance$" + "--previous-state" = "$check_previous_state$" + "--state-duration" = "$check_state_duration$" + "--hostname" = "$check_hostname$" + "--servicedesc" = "$check_servicedesc$" + } + vars.check_critical_on_host = "$host.total_services_critical$" + vars.check_warning_on_host = "$host.total_services_warning$" + vars.check_type = "random" + vars.check_failchange = "5%" + vars.check_previous_state = "$service.state$" + vars.check_duration = "$service.duration_sec$" + vars.check_hostname = "$host.name$" + vars.check_servicedesc = "$service.name$" +} + +object CheckCommand "dummy-host" { + import "dummy-host-generic" +} + +object CheckCommand "dummy-service" { + import "dummy-service-generic" +} + +// Hostgroups + +object HostGroup "all-hosts" { + display_name = "All hosts on the system" + assign where true +} + +object HostGroup "all-ok" { + display_name = "All ok hosts" + assign where regex("^test-ok", host.name) +} + +object HostGroup "all-chaos" { + display_name = "All chaos hosts" + assign where regex("^test-chaos", host.name) +} + +object HostGroup "all-down" { + display_name = "All down hosts" + assign where regex("^test-down", host.name) +} + +object HostGroup "all-up" { + display_name = "All ok hosts" + assign where regex("^test-ok", host.name) +} + +object HostGroup "all-unreachable" { + display_name = "All ok hosts" + assign where regex("^test-unreachable", host.name) +} + +object HostGroup "all-pending" { + display_name = "All ok hosts" + assign where regex("^test-pending", host.name) +} + +// Servicegroups + +object ServiceGroup "service-ok" { + display_name = "All ok services" + assign where regex("^service-ok", service.name) +} + +object ServiceGroup "service-warning" { + display_name = "All warning services" + assign where regex("^service-warning", service.name) +} + +object ServiceGroup "service-critical" { + display_name = "All critical services" + assign where regex("^service-critical", service.name) +} + +object ServiceGroup "service-unknown" { + display_name = "All unknown services" + assign where regex("^service-unknown", service.name) +} + +object ServiceGroup "service-flapping" { + display_name = "All flapping services" + assign where regex("^service-flapping", service.name) +} + + +object ServiceGroup "service-pending" { + display_name = "All pending services" + assign where regex("^service-pending", service.name) +} + + +// --------------------------------------------------------------------------------------------------------------------- +// Services +// --------------------------------------------------------------------------------------------------------------------- + +apply Service "service-ok-001" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "ok" + assign where match("*ok*", host.vars.check_config) +} + +apply Service "service-ok-002" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "ok" + assign where match("*ok*", host.vars.check_config) +} + +apply Service "service-ok-003" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "ok" + assign where match("*ok*", host.vars.check_config) +} + +apply Service "service-warning-001" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "warning" + assign where match("*warning*", host.vars.check_config) +} + +apply Service "service-warning-002" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "warning" + assign where match("*warning*", host.vars.check_config) +} + +apply Service "service-warning-003" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "warning" + assign where match("*warning*", host.vars.check_config) +} + +apply Service "service-critical-001" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "critical" + assign where match("*critical*", host.vars.check_config) +} + +apply Service "service-critical-002" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "critical" + assign where match("*critical*", host.vars.check_config) +} + +apply Service "service-critical-003" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "critical" + assign where match("*critical*", host.vars.check_config) +} + +apply Service "service-flapping-001" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "flap" + assign where match("*flap*", host.vars.check_config) +} + +apply Service "service-flapping-002" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "flap" + assign where match("*flap*", host.vars.check_config) +} + +apply Service "service-flapping-003" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "flap" + assign where match("*flap*", host.vars.check_config) +} + +apply Service "service-chaos-001" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "random" + assign where match("*random*", host.vars.check_config) +} + +apply Service "service-chaos-002" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "random" + assign where match("*random*", host.vars.check_config) +} + +apply Service "service-chaos-003" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "random" + assign where match("*random*", host.vars.check_config) +} + +apply Service "service-unknown-001" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "unknown" + assign where match("*unknown*", host.vars.check_config) +} + +apply Service "service-unknown-002" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "unknown" + assign where match("*unknown*", host.vars.check_config) +} + +apply Service "service-unknown-003" { + import "generic-service" + check_command = "dummy-service" + vars.check_type = "unknown" + assign where match("*unknown*", host.vars.check_config) +} + +apply Service "service-pending-001" { + import "generic-service" + check_command = "dummy-service" + enable_active_checks = false + vars.check_type = "pending" + assign where match("*pending*", host.vars.check_config) +} + +apply Service "service-pending-002" { + import "generic-service" + check_command = "dummy-service" + enable_active_checks = false + vars.check_type = "unknown" + assign where match("*pending*", host.vars.check_config) +} + +apply Service "service-pending-003" { + import "generic-service" + check_command = "dummy-service" + enable_active_checks = false + vars.check_type = "pending" + assign where match("*pending*", host.vars.check_config) +} + + +// --------------------------------------------------------------------------------------------------------------------- +// Hosts +// --------------------------------------------------------------------------------------------------------------------- + +// OK + +object Host "test-ok-001" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_config = "ok" +} + +object Host "test-ok-002" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_config = "ok" +} + +object Host "test-ok-003" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_config = "ok" +} + +object Host "test-ok-004" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_config = "ok" +} + +object Host "test-ok-005" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_config = "ok" +} + +object Host "test-ok-006" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_config = "ok" +} + +object Host "test-ok-007" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_config = "ok" +} + +object Host "test-ok-008" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_config = "ok" +} + +object Host "test-ok-009" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_config = "ok" +} + +object Host "test-ok-010" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_config = "ok" +} + +// Chaotic + +object Host "test-chaos-001" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "random" + vars.check_config = "random,flap" +} + +object Host "test-chaos-002" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "random" + vars.check_config = "random,flap" +} + +object Host "test-chaos-003" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "random" + vars.check_config = "random,flap" +} + +object Host "test-chaos-004" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "random" + vars.check_config = "random,flap" +} + +object Host "test-chaos-005" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "random" + vars.check_config = "random,flap" +} + +object Host "test-chaos-006" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "random" + vars.check_config = "random,flap" +} + +object Host "test-chaos-007" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "random" + vars.check_config = "random,flap" +} + +object Host "test-chaos-008" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "random" + vars.check_config = "random,flap" +} + +object Host "test-chaos-009" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "random" + vars.check_config = "random,flap" +} + +object Host "test-chaos-010" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "random" + vars.check_config = "random,flap" +} + +// Down + +object Host "test-down-001" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "down" + vars.check_config = "warning,critical" +} + +object Host "test-down-002" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "down" + vars.check_config = "warning,critical" +} + +object Host "test-down-003" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "down" + vars.check_config = "warning,critical" +} + +object Host "test-down-004" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "down" + vars.check_config = "warning,critical" +} + +object Host "test-down-005" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "down" + vars.check_config = "warning,critical" +} + +object Host "test-down-006" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "down" + vars.check_config = "warning,critical" +} + +object Host "test-down-007" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "down" + vars.check_config = "warning,critical" +} + +object Host "test-down-008" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "down" + vars.check_config = "warning,critical" +} + +object Host "test-down-009" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "down" + vars.check_config = "warning,critical" +} + +object Host "test-down-010" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "down" + vars.check_config = "warning,critical" +} + +// Unreachable + +object Host "test-unreachable-001" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "unreachable" + vars.check_config = "unknown" +} + +object Host "test-unreachable-002" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "unreachable" + vars.check_config = "unknown" +} + +object Host "test-unreachable-003" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "unreachable" + vars.check_config = "unknown" +} + +object Host "test-unreachable-004" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "unreachable" + vars.check_config = "unknown" +} + +object Host "test-unreachable-005" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "unreachable" + vars.check_config = "unknown" +} + +object Host "test-unreachable-006" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "unreachable" + vars.check_config = "unknown" +} + +object Host "test-unreachable-007" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "unreachable" + vars.check_config = "unknown" +} + +object Host "test-unreachable-008" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "unreachable" + vars.check_config = "unknown" +} + +object Host "test-unreachable-009" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "unreachable" + vars.check_config = "unknown" +} + +object Host "test-unreachable-010" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "unreachable" + vars.check_config = "unknown" +} + +// Pending + +object Host "test-pending-001" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "pending" + vars.check_config = "pending" +} + +object Host "test-pending-002" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "pending" + vars.check_config = "pending" +} + +object Host "test-pending-003" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "pending" + vars.check_config = "pending" +} + +object Host "test-pending-004" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "pending" + vars.check_config = "pending" +} + +object Host "test-pending-005" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "pending" + vars.check_config = "pending" +} + +object Host "test-pending-006" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "pending" + vars.check_config = "pending" +} + +object Host "test-pending-007" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "pending" + vars.check_config = "pending" +} + +object Host "test-pending-008" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "pending" + vars.check_config = "pending" +} + +object Host "test-pending-009" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "pending" + vars.check_config = "pending" +} + +object Host "test-pending-010" { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + vars.check_type = "pending" + vars.check_config = "pending" +} + +// EOF \ No newline at end of file diff --git a/.vagrant-puppet/files/etc/icinga2/features-available/ido-mysql.conf b/.vagrant-puppet/files/etc/icinga2/features-available/ido-mysql.conf new file mode 100644 index 000000000..3e278fe2d --- /dev/null +++ b/.vagrant-puppet/files/etc/icinga2/features-available/ido-mysql.conf @@ -0,0 +1,13 @@ +/** + * The db_ido_mysql library implements IDO functionality + * for MySQL. + */ + +library "db_ido_mysql" + +object IdoMysqlConnection "ido-mysql" { + user = "icinga2", + password = "icinga2", + host = "localhost", + database = "icinga2" +} diff --git a/.vagrant-puppet/files/etc/icinga2/features-available/ido-pgsql.conf b/.vagrant-puppet/files/etc/icinga2/features-available/ido-pgsql.conf new file mode 100644 index 000000000..e16cc6c3d --- /dev/null +++ b/.vagrant-puppet/files/etc/icinga2/features-available/ido-pgsql.conf @@ -0,0 +1,13 @@ +/** + * The db_ido_pgsql library implements IDO functionality + * for PostgreSQL. + */ + +library "db_ido_pgsql" + +object IdoPgsqlConnection "ido-pgsql" { + user = "icinga2", + password = "icinga2", + host = "localhost", + database = "icinga2" +} diff --git a/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/instances.ini b/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/instances.ini index 2f54e11e3..037baa8b9 100644 --- a/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/instances.ini +++ b/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/instances.ini @@ -1,2 +1,2 @@ [icinga] -path = "/usr/local/icinga-mysql/var/rw/icinga.cmd" +path = "/var/run/icinga2/cmd/icinga2.cmd" diff --git a/.vagrant-puppet/files/etc/icingaweb/resources.ini b/.vagrant-puppet/files/etc/icingaweb/resources.ini index 2ef51e921..3935906eb 100644 --- a/.vagrant-puppet/files/etc/icingaweb/resources.ini +++ b/.vagrant-puppet/files/etc/icingaweb/resources.ini @@ -12,9 +12,9 @@ type = db db = mysql host = localhost port = 3306 -password = icinga -username = icinga -dbname = icinga +password = icinga2 +username = icinga2 +dbname = icinga2 [statusdat] type = statusdat diff --git a/.vagrant-puppet/manifests/default.pp b/.vagrant-puppet/manifests/default.pp index 9c5666a89..526bdda2b 100644 --- a/.vagrant-puppet/manifests/default.pp +++ b/.vagrant-puppet/manifests/default.pp @@ -5,17 +5,25 @@ include openldap Exec { path => '/bin:/usr/bin:/sbin' } -$icingaVersion = '1.9.4' -$icinga2Version = '0.0.6' +$icingaVersion = '1.11.2' +$icinga2Version = '0.0.10' exec { 'create-mysql-icinga-db': unless => 'mysql -uicinga -picinga icinga', command => 'mysql -uroot -e "CREATE DATABASE icinga; \ - GRANT ALL ON icinga.* TO icinga@localhost \ + GRANT SELECT,INSERT,UPDATE,DELETE ON icinga.* TO icinga@localhost \ IDENTIFIED BY \'icinga\';"', require => Service['mysqld'] } +exec { 'create-mysql-icinga2-db': + unless => 'mysql -uicinga2 -picinga2 icinga2', + command => 'mysql -uroot -e "CREATE DATABASE icinga2; \ + GRANT SELECT,INSERT,UPDATE,DELETE ON icinga2.* to icinga2@localhost \ + IDENTIFIED BY \'icinga2\';"', + require => Service['mysqld'] +} + exec{ 'create-pgsql-icinga-db': unless => 'sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname=\'icinga\'" | grep -q 1', command => 'sudo -u postgres psql -c "CREATE ROLE icinga WITH LOGIN PASSWORD \'icingaweb\';" && \ @@ -40,6 +48,11 @@ group { 'icinga-cmd': ensure => present } +group { 'icingacmd': + ensure => present, + require => Exec['install icinga2'] +} + user { 'icinga': ensure => present, groups => 'icinga-cmd', @@ -47,8 +60,8 @@ user { 'icinga': } user { 'apache': - groups => ['icinga-cmd', 'vagrant'], - require => [ Class['apache'], Group['icinga-cmd'] ] + groups => ['icinga-cmd', 'vagrant', 'icingacmd'], + require => [ Class['apache'], Group['icinga-cmd'], Group['icingacmd'] ] } cmmi { 'icinga-mysql': @@ -104,7 +117,7 @@ file { '/etc/init.d/ido2db-pgsql': exec { 'populate-icinga-mysql-db': unless => 'mysql -uicinga -picinga icinga -e "SELECT * FROM icinga_dbversion;" &> /dev/null', - command => "mysql -uicinga -picinga icinga < /usr/local/src/icinga-mysql/icinga-${icingaVersion}/module/idoutils/db/mysql/mysql.sql", + command => "mysql -uroot icinga < /usr/local/src/icinga-mysql/icinga-${icingaVersion}/module/idoutils/db/mysql/mysql.sql", require => [ Cmmi['icinga-mysql'], Exec['create-mysql-icinga-db'] ] } @@ -330,7 +343,92 @@ package { ['cmake', 'boost-devel', 'bison', 'flex']: ensure => installed } -#cmmi { 'icinga2': +yumrepo { 'icinga2-repo': + baseurl => "http://packages.icinga.org/epel/6/release/", + enabled => '0', + gpgcheck => '1', + gpgkey => 'http://packages.icinga.org/icinga.key', + descr => "Icinga Repository - ${::architecture}" +} + +exec { 'install icinga2': + command => 'yum -d 0 -e 0 -y --enablerepo=icinga2-repo install icinga2', + unless => 'rpm -qa | grep icinga2', + require => Yumrepo['icinga2-repo'] +} + +exec { 'install icinga2-classicui-config': + command => 'yum -d 0 -e 0 -y --enablerepo=icinga2-repo install icinga2-classicui-config', + unless => 'rpm -qa | grep icinga2-classicui-config', + require => [ Yumrepo['icinga2-repo'], Exec['install icinga2'], Exec['install icinga2-ido-mysql'] ] +} + +exec { 'install icinga2-ido-mysql': + command => 'yum -d 0 -e 0 -y --enablerepo=icinga2-repo install icinga2-ido-mysql', + unless => 'rpm -qa | grep icinga2-ido-mysql', + require => [ Yumrepo['icinga2-repo'], Exec['install icinga2'] ], +} + +exec { 'install nagios-plugins-all': + command => 'yum -d 0 -e 0 -y --enablerepo=epel install nagios-plugins-all', + unless => 'rpm -qa | grep nagios-plugins-all', + require => [ Class['epel'], Exec['install icinga2'] ], +} + +file { '/etc/icinga2/features-enabled/': + ensure => directory, + owner => icinga, + group => icinga, + require => Exec['install icinga2-ido-mysql'] +} + +file { '/etc/icinga2/features-available/ido-mysql.conf': + source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icinga2/features-available/ido-mysql.conf', + owner => 'icinga', + group => 'icinga', + require => Exec['install icinga2-ido-mysql'] +} + +file { '/etc/icinga2/features-enabled/ido-mysql.conf': + ensure => 'link', + target => '/etc/icinga2/features-available/ido-mysql.conf', + owner => 'root', + group => 'root', + require => Exec['install icinga2-ido-mysql'] +} + +file { '/etc/icinga2/conf.d/test-config.conf': + source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf', + owner => 'icinga', + group => 'icinga', + require => Exec['install icinga2'] +} + +file { '/etc/icinga2/conf.d/commands.conf': + source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icinga2/conf.d/commands.conf', + owner => 'icinga', + group => 'icinga', + require => Exec['install icinga2'] +} + +service { 'icinga2': + ensure => running, + require => [ + Exec['install icinga2'], + File['/etc/icinga2/features-enabled/ido-mysql.conf'], + File['/etc/icinga2/conf.d/test-config.conf'], + File['/etc/icinga2/conf.d/commands.conf'] + ] +} + + +exec { 'populate-icinga2-mysql-db': + unless => 'mysql -uicinga2 -picinga2 icinga2 -e "SELECT * FROM icinga_dbversion;" &> /dev/null', + command => "mysql -uroot icinga2 < /usr/share/doc/icinga2-ido-mysql-$icinga2Version/schema/mysql.sql", + require => [ Exec['create-mysql-icinga2-db'], Exec['install icinga2-ido-mysql'] ] +} + +# cmmi { 'icinga2': # url => "https://github.com/Icinga/icinga2/releases/download/v${icinga2Version}/icinga2-${icinga2Version}.tar.gz", # output => "icinga2-${icinga2Version}.tar.gz", # configure_command => 'mkdir build &> /dev/null || true && cd build && sudo cmake ..', @@ -338,7 +436,7 @@ package { ['cmake', 'boost-devel', 'bison', 'flex']: # make => 'true && cd build/ && make && make install', # require => Package[ ['cmake', 'boost-devel', 'bison', 'flex'] ], # make_timeout => 900 -#} +# } #configure { 'icingaweb': # path => '/vagrant', @@ -699,6 +797,6 @@ file { '/etc/icingaweb/dashboard/dashboard.ini': group => 'apache', } -pear::package { 'deepend/Mockery': - channel => 'pear.survivethedeepend.com' -} +# pear::package { 'deepend/Mockery': +# channel => 'pear.survivethedeepend.com' +# } From fb44940deae8c5f6ae3f12fdb0dfc40c68de00e4 Mon Sep 17 00:00:00 2001 From: Marius Hein Date: Fri, 9 May 2014 15:09:44 +0200 Subject: [PATCH 02/55] Vagrant/Icinga2: Optimize test configuration --- .../files/etc/icinga2/conf.d/test-config.conf | 641 +++--------------- 1 file changed, 109 insertions(+), 532 deletions(-) diff --git a/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf b/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf index 279f2ec1a..edf3ecffd 100644 --- a/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf +++ b/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf @@ -62,7 +62,7 @@ object HostGroup "all-ok" { object HostGroup "all-chaos" { display_name = "All chaos hosts" - assign where regex("^test-chaos", host.name) + assign where regex("^test-random", host.name) } object HostGroup "all-down" { @@ -123,559 +123,136 @@ object ServiceGroup "service-pending" { // Services // --------------------------------------------------------------------------------------------------------------------- -apply Service "service-ok-001" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "ok" - assign where match("*ok*", host.vars.check_config) +function createService(filter, num, checkEnabled) { + apply Service "service-" + filter + "-" + num { + import "generic-service" + check_command = "dummy-service" + enable_active_checks = checkEnabled + vars.check_type = filter + assign where match("*" + filter + "*", host.vars.check_config) + } } -apply Service "service-ok-002" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "ok" - assign where match("*ok*", host.vars.check_config) -} +createService("ok", "001", true) +createService("ok", "002", true) +createService("ok", "003", true) +createService("ok", "004", true) -apply Service "service-ok-003" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "ok" - assign where match("*ok*", host.vars.check_config) -} +createService("warning", "001", true) +createService("warning", "002", true) +createService("warning", "003", true) +createService("warning", "004", true) -apply Service "service-warning-001" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "warning" - assign where match("*warning*", host.vars.check_config) -} +createService("critical", "001", true) +createService("critical", "002", true) +createService("critical", "003", true) +createService("critical", "004", true) -apply Service "service-warning-002" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "warning" - assign where match("*warning*", host.vars.check_config) -} +createService("flap", "001", true) +createService("flap", "002", true) +createService("flap", "003", true) +createService("flap", "004", true) -apply Service "service-warning-003" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "warning" - assign where match("*warning*", host.vars.check_config) -} +createService("random", "001", true) +createService("random", "002", true) +createService("random", "003", true) +createService("random", "004", true) -apply Service "service-critical-001" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "critical" - assign where match("*critical*", host.vars.check_config) -} - -apply Service "service-critical-002" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "critical" - assign where match("*critical*", host.vars.check_config) -} - -apply Service "service-critical-003" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "critical" - assign where match("*critical*", host.vars.check_config) -} - -apply Service "service-flapping-001" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "flap" - assign where match("*flap*", host.vars.check_config) -} - -apply Service "service-flapping-002" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "flap" - assign where match("*flap*", host.vars.check_config) -} - -apply Service "service-flapping-003" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "flap" - assign where match("*flap*", host.vars.check_config) -} - -apply Service "service-chaos-001" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "random" - assign where match("*random*", host.vars.check_config) -} - -apply Service "service-chaos-002" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "random" - assign where match("*random*", host.vars.check_config) -} - -apply Service "service-chaos-003" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "random" - assign where match("*random*", host.vars.check_config) -} - -apply Service "service-unknown-001" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "unknown" - assign where match("*unknown*", host.vars.check_config) -} - -apply Service "service-unknown-002" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "unknown" - assign where match("*unknown*", host.vars.check_config) -} - -apply Service "service-unknown-003" { - import "generic-service" - check_command = "dummy-service" - vars.check_type = "unknown" - assign where match("*unknown*", host.vars.check_config) -} - -apply Service "service-pending-001" { - import "generic-service" - check_command = "dummy-service" - enable_active_checks = false - vars.check_type = "pending" - assign where match("*pending*", host.vars.check_config) -} - -apply Service "service-pending-002" { - import "generic-service" - check_command = "dummy-service" - enable_active_checks = false - vars.check_type = "unknown" - assign where match("*pending*", host.vars.check_config) -} - -apply Service "service-pending-003" { - import "generic-service" - check_command = "dummy-service" - enable_active_checks = false - vars.check_type = "pending" - assign where match("*pending*", host.vars.check_config) -} +createService("unknown", "001", true) +createService("unknown", "002", true) +createService("unknown", "003", true) +createService("unknown", "004", true) +createService("pending", "001", false) +createService("pending", "002", false) +createService("pending", "003", false) +createService("pending", "004", false) // --------------------------------------------------------------------------------------------------------------------- // Hosts // --------------------------------------------------------------------------------------------------------------------- +function createHost(checkType, checkConfig, num, checkEnabled) { + object Host "test-" + checkType + "-" + num { + import "generic-host" + address = "127.0.0.1" + check_command = "dummy-host" + enable_active_checks = checkEnabled + vars.check_type = checkType + vars.check_config = checkConfig + } +} + // OK - -object Host "test-ok-001" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_config = "ok" -} - -object Host "test-ok-002" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_config = "ok" -} - -object Host "test-ok-003" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_config = "ok" -} - -object Host "test-ok-004" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_config = "ok" -} - -object Host "test-ok-005" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_config = "ok" -} - -object Host "test-ok-006" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_config = "ok" -} - -object Host "test-ok-007" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_config = "ok" -} - -object Host "test-ok-008" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_config = "ok" -} - -object Host "test-ok-009" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_config = "ok" -} - -object Host "test-ok-010" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_config = "ok" -} +createHost("ok", "ok", "001", true) +createHost("ok", "ok", "002", true) +createHost("ok", "ok", "003", true) +createHost("ok", "ok", "004", true) +createHost("ok", "ok", "005", true) +createHost("ok", "ok", "006", true) +createHost("ok", "ok", "007", true) +createHost("ok", "ok", "008", true) +createHost("ok", "ok", "009", true) +createHost("ok", "ok", "010", true) // Chaotic - -object Host "test-chaos-001" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "random" - vars.check_config = "random,flap" -} - -object Host "test-chaos-002" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "random" - vars.check_config = "random,flap" -} - -object Host "test-chaos-003" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "random" - vars.check_config = "random,flap" -} - -object Host "test-chaos-004" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "random" - vars.check_config = "random,flap" -} - -object Host "test-chaos-005" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "random" - vars.check_config = "random,flap" -} - -object Host "test-chaos-006" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "random" - vars.check_config = "random,flap" -} - -object Host "test-chaos-007" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "random" - vars.check_config = "random,flap" -} - -object Host "test-chaos-008" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "random" - vars.check_config = "random,flap" -} - -object Host "test-chaos-009" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "random" - vars.check_config = "random,flap" -} - -object Host "test-chaos-010" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "random" - vars.check_config = "random,flap" -} +createHost("random", "random,flap", "001", true) +createHost("random", "random,flap", "002", true) +createHost("random", "random,flap", "003", true) +createHost("random", "random,flap", "004", true) +createHost("random", "random,flap", "005", true) +createHost("random", "random,flap", "006", true) +createHost("random", "random,flap", "007", true) +createHost("random", "random,flap", "008", true) +createHost("random", "random,flap", "009", true) +createHost("random", "random,flap", "010", true) // Down - -object Host "test-down-001" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "down" - vars.check_config = "warning,critical" -} - -object Host "test-down-002" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "down" - vars.check_config = "warning,critical" -} - -object Host "test-down-003" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "down" - vars.check_config = "warning,critical" -} - -object Host "test-down-004" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "down" - vars.check_config = "warning,critical" -} - -object Host "test-down-005" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "down" - vars.check_config = "warning,critical" -} - -object Host "test-down-006" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "down" - vars.check_config = "warning,critical" -} - -object Host "test-down-007" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "down" - vars.check_config = "warning,critical" -} - -object Host "test-down-008" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "down" - vars.check_config = "warning,critical" -} - -object Host "test-down-009" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "down" - vars.check_config = "warning,critical" -} - -object Host "test-down-010" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "down" - vars.check_config = "warning,critical" -} +createHost("down", "warning,critical", "001", true) +createHost("down", "warning,critical", "002", true) +createHost("down", "warning,critical", "003", true) +createHost("down", "warning,critical", "004", true) +createHost("down", "warning,critical", "005", true) +createHost("down", "warning,critical", "006", true) +createHost("down", "warning,critical", "007", true) +createHost("down", "warning,critical", "008", true) +createHost("down", "warning,critical", "009", true) +createHost("down", "warning,critical", "010", true) // Unreachable - -object Host "test-unreachable-001" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "unreachable" - vars.check_config = "unknown" -} - -object Host "test-unreachable-002" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "unreachable" - vars.check_config = "unknown" -} - -object Host "test-unreachable-003" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "unreachable" - vars.check_config = "unknown" -} - -object Host "test-unreachable-004" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "unreachable" - vars.check_config = "unknown" -} - -object Host "test-unreachable-005" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "unreachable" - vars.check_config = "unknown" -} - -object Host "test-unreachable-006" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "unreachable" - vars.check_config = "unknown" -} - -object Host "test-unreachable-007" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "unreachable" - vars.check_config = "unknown" -} - -object Host "test-unreachable-008" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "unreachable" - vars.check_config = "unknown" -} - -object Host "test-unreachable-009" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "unreachable" - vars.check_config = "unknown" -} - -object Host "test-unreachable-010" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "unreachable" - vars.check_config = "unknown" -} +createHost("unreachable", "unknown", "001", true) +createHost("unreachable", "unknown", "002", true) +createHost("unreachable", "unknown", "003", true) +createHost("unreachable", "unknown", "004", true) +createHost("unreachable", "unknown", "005", true) +createHost("unreachable", "unknown", "006", true) +createHost("unreachable", "unknown", "007", true) +createHost("unreachable", "unknown", "008", true) +createHost("unreachable", "unknown", "009", true) +createHost("unreachable", "unknown", "010", true) // Pending +createHost("pending", "pending", "001", false) +createHost("pending", "pending", "002", false) +createHost("pending", "pending", "003", false) +createHost("pending", "pending", "004", false) +createHost("pending", "pending", "005", false) +createHost("pending", "pending", "006", false) +createHost("pending", "pending", "007", false) +createHost("pending", "pending", "008", false) +createHost("pending", "pending", "009", false) +createHost("pending", "pending", "010", false) -object Host "test-pending-001" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "pending" - vars.check_config = "pending" -} - -object Host "test-pending-002" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "pending" - vars.check_config = "pending" -} - -object Host "test-pending-003" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "pending" - vars.check_config = "pending" -} - -object Host "test-pending-004" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "pending" - vars.check_config = "pending" -} - -object Host "test-pending-005" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "pending" - vars.check_config = "pending" -} - -object Host "test-pending-006" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "pending" - vars.check_config = "pending" -} - -object Host "test-pending-007" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "pending" - vars.check_config = "pending" -} - -object Host "test-pending-008" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "pending" - vars.check_config = "pending" -} - -object Host "test-pending-009" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "pending" - vars.check_config = "pending" -} - -object Host "test-pending-010" { - import "generic-host" - address = "127.0.0.1" - check_command = "dummy-host" - vars.check_type = "pending" - vars.check_config = "pending" -} +// Flapping +createHost("flap", "flap", "001", true) +createHost("flap", "flap", "002", true) +createHost("flap", "flap", "003", true) +createHost("flap", "flap", "004", true) +createHost("flap", "flap", "005", true) +createHost("flap", "flap", "006", true) +createHost("flap", "flap", "007", true) +createHost("flap", "flap", "008", true) +createHost("flap", "flap", "009", true) +createHost("flap", "flap", "010", true) // EOF \ No newline at end of file From 8d42914a84281dc203edcb2034aa59b40fca26af Mon Sep 17 00:00:00 2001 From: Marius Hein Date: Fri, 9 May 2014 15:37:34 +0200 Subject: [PATCH 03/55] Vagrant/Icinga2: Upgrade to snapshots and optimize configuration refs #6127 --- .../files/etc/icinga2/conf.d/test-config.conf | 134 ++++-------------- .vagrant-puppet/manifests/default.pp | 2 +- 2 files changed, 26 insertions(+), 110 deletions(-) diff --git a/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf b/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf index edf3ecffd..ee13a0ebb 100644 --- a/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf +++ b/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf @@ -40,6 +40,7 @@ template CheckCommand "dummy-service-generic" { vars.check_servicedesc = "$service.name$" } +// Concrete check commands object CheckCommand "dummy-host" { import "dummy-host-generic" } @@ -49,7 +50,6 @@ object CheckCommand "dummy-service" { } // Hostgroups - object HostGroup "all-hosts" { display_name = "All hosts on the system" assign where true @@ -86,7 +86,6 @@ object HostGroup "all-pending" { } // Servicegroups - object ServiceGroup "service-ok" { display_name = "All ok services" assign where regex("^service-ok", service.name) @@ -118,13 +117,18 @@ object ServiceGroup "service-pending" { assign where regex("^service-pending", service.name) } +// Config helper +function loop(count, func) { + count == 1 || loop(count - 1, func) + func(count) +} // --------------------------------------------------------------------------------------------------------------------- // Services // --------------------------------------------------------------------------------------------------------------------- function createService(filter, num, checkEnabled) { - apply Service "service-" + filter + "-" + num { + apply Service "service-" + filter + "-" + string(num) { import "generic-service" check_command = "dummy-service" enable_active_checks = checkEnabled @@ -133,47 +137,22 @@ function createService(filter, num, checkEnabled) { } } -createService("ok", "001", true) -createService("ok", "002", true) -createService("ok", "003", true) -createService("ok", "004", true) - -createService("warning", "001", true) -createService("warning", "002", true) -createService("warning", "003", true) -createService("warning", "004", true) - -createService("critical", "001", true) -createService("critical", "002", true) -createService("critical", "003", true) -createService("critical", "004", true) - -createService("flap", "001", true) -createService("flap", "002", true) -createService("flap", "003", true) -createService("flap", "004", true) - -createService("random", "001", true) -createService("random", "002", true) -createService("random", "003", true) -createService("random", "004", true) - -createService("unknown", "001", true) -createService("unknown", "002", true) -createService("unknown", "003", true) -createService("unknown", "004", true) - -createService("pending", "001", false) -createService("pending", "002", false) -createService("pending", "003", false) -createService("pending", "004", false) +loop(4, lambda num: { + createService("ok", num, true) + createService("warning", num, true) + createService("critical", num, true) + createService("flap", num, true) + createService("random", num, true) + createService("unknown", num, true) + createService("pending", num, false) +}) // --------------------------------------------------------------------------------------------------------------------- // Hosts // --------------------------------------------------------------------------------------------------------------------- function createHost(checkType, checkConfig, num, checkEnabled) { - object Host "test-" + checkType + "-" + num { + object Host "test-" + checkType + "-" + string(num) { import "generic-host" address = "127.0.0.1" check_command = "dummy-host" @@ -183,76 +162,13 @@ function createHost(checkType, checkConfig, num, checkEnabled) { } } -// OK -createHost("ok", "ok", "001", true) -createHost("ok", "ok", "002", true) -createHost("ok", "ok", "003", true) -createHost("ok", "ok", "004", true) -createHost("ok", "ok", "005", true) -createHost("ok", "ok", "006", true) -createHost("ok", "ok", "007", true) -createHost("ok", "ok", "008", true) -createHost("ok", "ok", "009", true) -createHost("ok", "ok", "010", true) - -// Chaotic -createHost("random", "random,flap", "001", true) -createHost("random", "random,flap", "002", true) -createHost("random", "random,flap", "003", true) -createHost("random", "random,flap", "004", true) -createHost("random", "random,flap", "005", true) -createHost("random", "random,flap", "006", true) -createHost("random", "random,flap", "007", true) -createHost("random", "random,flap", "008", true) -createHost("random", "random,flap", "009", true) -createHost("random", "random,flap", "010", true) - -// Down -createHost("down", "warning,critical", "001", true) -createHost("down", "warning,critical", "002", true) -createHost("down", "warning,critical", "003", true) -createHost("down", "warning,critical", "004", true) -createHost("down", "warning,critical", "005", true) -createHost("down", "warning,critical", "006", true) -createHost("down", "warning,critical", "007", true) -createHost("down", "warning,critical", "008", true) -createHost("down", "warning,critical", "009", true) -createHost("down", "warning,critical", "010", true) - -// Unreachable -createHost("unreachable", "unknown", "001", true) -createHost("unreachable", "unknown", "002", true) -createHost("unreachable", "unknown", "003", true) -createHost("unreachable", "unknown", "004", true) -createHost("unreachable", "unknown", "005", true) -createHost("unreachable", "unknown", "006", true) -createHost("unreachable", "unknown", "007", true) -createHost("unreachable", "unknown", "008", true) -createHost("unreachable", "unknown", "009", true) -createHost("unreachable", "unknown", "010", true) - -// Pending -createHost("pending", "pending", "001", false) -createHost("pending", "pending", "002", false) -createHost("pending", "pending", "003", false) -createHost("pending", "pending", "004", false) -createHost("pending", "pending", "005", false) -createHost("pending", "pending", "006", false) -createHost("pending", "pending", "007", false) -createHost("pending", "pending", "008", false) -createHost("pending", "pending", "009", false) -createHost("pending", "pending", "010", false) - -// Flapping -createHost("flap", "flap", "001", true) -createHost("flap", "flap", "002", true) -createHost("flap", "flap", "003", true) -createHost("flap", "flap", "004", true) -createHost("flap", "flap", "005", true) -createHost("flap", "flap", "006", true) -createHost("flap", "flap", "007", true) -createHost("flap", "flap", "008", true) -createHost("flap", "flap", "009", true) -createHost("flap", "flap", "010", true) +loop(10, lambda num: { + createHost("ok", "ok", num, true) + createHost("random", "random,flap", num, true) + createHost("down", "warning,critical", num, true) + createHost("unreachable", "unknown", num, true) + createHost("pending", "pending", num, false) + createHost("flap", "flap", num, true) + }) // EOF \ No newline at end of file diff --git a/.vagrant-puppet/manifests/default.pp b/.vagrant-puppet/manifests/default.pp index 526bdda2b..4d30e58c4 100644 --- a/.vagrant-puppet/manifests/default.pp +++ b/.vagrant-puppet/manifests/default.pp @@ -344,7 +344,7 @@ package { ['cmake', 'boost-devel', 'bison', 'flex']: } yumrepo { 'icinga2-repo': - baseurl => "http://packages.icinga.org/epel/6/release/", + baseurl => "http://packages.icinga.org/epel/6/snapshot/", enabled => '0', gpgcheck => '1', gpgkey => 'http://packages.icinga.org/icinga.key', From d681031b7b81b0733ab948feb963b1d3e9821781 Mon Sep 17 00:00:00 2001 From: Marius Hein Date: Fri, 9 May 2014 18:40:46 +0200 Subject: [PATCH 04/55] Vagrant/Icinga2: Add dependencies for test config refs #6127 --- .vagrant-puppet/manifests/default.pp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.vagrant-puppet/manifests/default.pp b/.vagrant-puppet/manifests/default.pp index 4d30e58c4..0119837f4 100644 --- a/.vagrant-puppet/manifests/default.pp +++ b/.vagrant-puppet/manifests/default.pp @@ -401,7 +401,7 @@ file { '/etc/icinga2/conf.d/test-config.conf': source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf', owner => 'icinga', group => 'icinga', - require => Exec['install icinga2'] + require => [ Exec['install icinga2'], Exec['create_monitoring_test_config'] ] } file { '/etc/icinga2/conf.d/commands.conf': @@ -421,7 +421,6 @@ service { 'icinga2': ] } - exec { 'populate-icinga2-mysql-db': unless => 'mysql -uicinga2 -picinga2 icinga2 -e "SELECT * FROM icinga_dbversion;" &> /dev/null', command => "mysql -uroot icinga2 < /usr/share/doc/icinga2-ido-mysql-$icinga2Version/schema/mysql.sql", From 87054c8121900532bdcc878bf90735e60f631014 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sat, 10 May 2014 09:10:58 +0200 Subject: [PATCH 05/55] Make sure line-endings for Puppet manifests are LFs only. fixes #6181 --- .gitignore | 3 ++- .vagrant-puppet/.gitattributes | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .vagrant-puppet/.gitattributes diff --git a/.gitignore b/.gitignore index d57bdee03..fbbc7a3e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ # Exclude all hidden files .* -# But not .gitignore, .vagrant-puppet, .htaccess and .gitkeep +# But not .gitignore, .gitattributes, .vagrant-puppet, .htaccess and .gitkeep !.gitignore +!.gitattributes !.vagrant-puppet !public/.htaccess !public/.htaccess.in diff --git a/.vagrant-puppet/.gitattributes b/.vagrant-puppet/.gitattributes new file mode 100644 index 000000000..af67531d8 --- /dev/null +++ b/.vagrant-puppet/.gitattributes @@ -0,0 +1 @@ +* -crlf From 793a0a061fdcffc782803ba521f389b61cbc67b8 Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Mon, 12 May 2014 15:40:59 +0200 Subject: [PATCH 06/55] Add validation for application name. refs #6129 --- application/forms/Config/LoggingForm.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/application/forms/Config/LoggingForm.php b/application/forms/Config/LoggingForm.php index eff629e09..3683c29b5 100644 --- a/application/forms/Config/LoggingForm.php +++ b/application/forms/Config/LoggingForm.php @@ -30,7 +30,7 @@ namespace Icinga\Form\Config; -use Zend_Config; +use \Zend_Config; use Icinga\Web\Form; use Icinga\Application\Icinga; use Icinga\Web\Form\Validator\WritablePathValidator; @@ -116,7 +116,19 @@ class LoggingForm extends Form 'required' => true, 'label' => t('Application Prefix'), 'helptext' => t('The name of the application by which to prefix syslog messages.'), - 'value' => $loggingConfig->get('application', 'icingaweb') + 'value' => $loggingConfig->get('application', 'icingaweb'), + 'validators' => array( + array( + 'Regex', + false, + array( + 'pattern' => '/^[^\W]+$/', + 'messages' => array( + 'regexNotMatch' => 'The application prefix cannot contain any whitespaces.' + ) + ) + ) + ) ) ); $this->addElement( From ced6e8f78f8c21c3cf5a3a660788a19465a1b6dc Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Mon, 12 May 2014 15:49:38 +0200 Subject: [PATCH 07/55] Initialize all empty ellements with their default values. refs #6098 --- application/forms/Config/LoggingForm.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/application/forms/Config/LoggingForm.php b/application/forms/Config/LoggingForm.php index 3683c29b5..81540a683 100644 --- a/application/forms/Config/LoggingForm.php +++ b/application/forms/Config/LoggingForm.php @@ -163,6 +163,16 @@ class LoggingForm extends Form $this->setSubmitLabel('{{SAVE_ICON}} Save Changes'); } + public function isValid($data) { + foreach ($this->getElements() as $key => $element) { + // Initialize all empty elements with their default values. + if (!isset($data[$key])) { + $data[$key] = $element->getValue(); + } + } + return parent::isValid($data); + } + /** * Return a Zend_Config object containing the state defined in this form * From 05943475661b87af4868f0cb596f63b2ce141410 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 13 May 2014 00:27:06 +0200 Subject: [PATCH 08/55] Refactor spec file and make rhel rpms work again. Refs #4075 --- .gitignore | 1 + icingaweb2.spec | 165 +++++++----------- packages/rhel/README | 57 ++++++ packages/rhel/etc/httpd/conf.d/icingaweb.conf | 12 ++ .../rhel/usr/share/icingaweb/public/.htaccess | 7 + .../rhel/usr/share/icingaweb/public/index.php | 5 + 6 files changed, 147 insertions(+), 100 deletions(-) create mode 100644 packages/rhel/README create mode 100644 packages/rhel/etc/httpd/conf.d/icingaweb.conf create mode 100644 packages/rhel/usr/share/icingaweb/public/.htaccess create mode 100644 packages/rhel/usr/share/icingaweb/public/index.php diff --git a/.gitignore b/.gitignore index fbbc7a3e7..a243728f3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ !.gitattributes !.vagrant-puppet !public/.htaccess +!packages/rhel/usr/share/icingaweb/public/.htaccess !public/.htaccess.in !.gitkeep diff --git a/icingaweb2.spec b/icingaweb2.spec index 35a50d8f4..72e5bddba 100644 --- a/icingaweb2.spec +++ b/icingaweb2.spec @@ -1,14 +1,15 @@ # $Id$ -# Authority: The icinga devel team -# Upstream: The icinga devel team +# Authority: The icinga devel team +# Upstream: The icinga devel team # ExcludeDist: el4 el3 %define revision 0 %define configdir %{_sysconfdir}/icingaweb -%define logdir %{_localstatedir}/log/icingaweb %define sharedir %{_datadir}/icingaweb %define prefixdir %{_datadir}/icingaweb +%define logdir %{sharedir}/log +#%define logdir %{_localstatedir}/log/icingaweb %if "%{_vendor}" == "suse" %define phpname php5 @@ -41,7 +42,7 @@ Summary: Open Source host, service and network monitoring Web UI Name: icingaweb2 -Version: 1.0.0 +Version: 0.0.1 Release: %{revision}%{?dist} License: GPLv2 Group: Applications/System @@ -52,7 +53,7 @@ BuildArch: noarch AutoReqProv: Off %endif -Source0: https://downloads.sourceforge.net/project/icinga/%{name}/%{version}/%{name}-%{version}.tar.gz +Source0: icingaweb2-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root @@ -92,108 +93,44 @@ Requires: %{phpname}-json Requires: apache2-mod_php5 %endif -Requires: %{name}-doc +Requires: %{phpzendname}-Db-Adapter-Pdo +Requires: %{phpzendname}-Db-Adapter-Pdo-Mysql + +Requires: php-Icinga %description IcingaWeb for Icinga 2 or Icinga 1.x using status data, IDOUtils or Livestatus as backend provider. -%package config-internal-mysql -Summary: config for internal mysql database +%package -n icingacli +Summary: Icinga CLI Group: Applications/System Requires: %{name} = %{version}-%{release} -Requires: %{phpzendname}-Db-Adapter-Pdo -Requires: %{phpzendname}-Db-Adapter-Pdo-Mysql +Requires: php-Icinga -%description config-internal-mysql -Configuration for internal mysql database. +%description -n icingacli +Icinga CLI using php-Icinga Icinga Web 2 backend. -%package config-internal-pgsql -Summary: config for internal pgsql database +%package -n php-Icinga +Summary: Icinga Web 2 PHP Libraries Group: Applications/System Requires: %{name} = %{version}-%{release} -Requires: %{phpzendname}-Db-Adapter-Pdo -Requires: %{phpzendname}-Db-Adapter-Pdo-Pgsql +Requires: %{phpname} >= 5.3.0 +Requires: %{phpzendname} -%description config-internal-pgsql -Configuration for internal pgsql database. -%package config-backend-statusdata-1x -Summary: Backend config for status data -Group: Applications/System -Requires: %{name} = %{version}-%{release} -Provides: %{name}-config-statusdata +%description -n php-Icinga +Icinga Web 2 PHP Libraries shared with icingacli. -%description config-backend-statusdata-1x -Backend config for status data provided by Icinga 1.x Core. -%package config-backend-ido-mysql-1x -Summary: Backend config for icinga 1.x ido mysql database -Group: Applications/System -Requires: %{name} = %{version}-%{release} -Requires: %{phpname}-mysql -Provides: %{name}-config-ido-mysql -%description config-backend-ido-mysql-1x -Backend config for ido mysql database provided by -Icinga 1.x IDOUtils with MySQL. - -%package config-backend-ido-pgsql-1x -Summary: Backend config for icinga 1.x ido pgsql database -Group: Applications/System -Requires: %{name} = %{version}-%{release} -Requires: %{phpname}-pgsql -Provides: %{name}-config-ido-pgsql - -%description config-backend-ido-pgsql-1x -Backend config for ido mysql database provided by -Icinga 1.x IDOUtils with PostgreSQL. - -%package config-backend-livestatus-1x -Summary: Backend config for icinga 1.x livestatus -Group: Applications/System -Requires: %{name} = %{version}-%{release} -Provides: %{name}-config-livestatus - -%description config-backend-livestatus-1x -Backend config for livestatus provided by Icinga 1.x -with mk_livestatus NEB module. - -%package config-backend-commands-1x -Summary: Backend config for icinga 1.x commands -Group: Applications/System -Requires: %{name} = %{version}-%{release} -Provides: %{name}-config-commands - -%description config-backend-commands-1x -Backend config for external command pipe provided by -Icinga 1.x %prep -%setup -q -n %{name}-%{version} +#%setup -q -n %{name}-%{version} +%setup -q -n %{name} %build -%configure \ - --prefix="%{prefixdir}" \ - --datadir="%{sharedir}" \ - --datarootdir="%{sharedir}" \ - --sysconfdir="%{configdir}" \ - --with-icingaweb-config-path='%{configdir}' \ - --with-icingaweb-log-path='%{logdir}' \ - --with-web-path='/icingaweb' \ - --with-httpd-config-path=%{apacheconfdir} \ - --with-web-user='%{apacheuser}' \ - --with-web-group='%{apachegroup}' \ - --with-internal-db-type='mysql' \ - --with-internal-db-name='icingaweb' \ - --with-internal-db-host='localhost' \ - --with-internal-db-port='3306' \ - --with-internal-db-pass='icingaweb' \ - --with-internal-db-user='icingaweb' \ - --with-internal-authentication=yes \ - --with-icinga-commandpipe='%{extcmdfile1x}' \ - --with-livestatus-socket='%{livestatussocket1x}' cat > README.RHEL.SUSE <<"EOF" IcingaWeb for RHEL and SUSE @@ -205,17 +142,40 @@ EOF %install [ "%{buildroot}" != "/" ] && [ -d "%{buildroot}" ] && rm -rf %{buildroot} -%{__mkdir} -p %{buildroot}/%{apacheconfdir} -%{__make} install \ - install-apache-config \ - DESTDIR="%{buildroot}" \ - INSTALL_OPTS="" \ - COMMAND_OPTS="" \ - INSTALL_OPTS_WEB="" \ - INIT_OPTS="" # prepare configuration for sub packages +# install rhel apache config +install -D -m0644 packages/rhel/etc/httpd/conf.d/icingaweb.conf %{buildroot}/%{apacheconfdir}/icingaweb.conf + +# install public, library, modules +%{__mkdir} -p %{buildroot}/%{sharedir} +%{__mkdir} -p %{buildroot}/%{logdir} +%{__mkdir} -p %{buildroot}/%{_sysconfdir}/icingaweb/enabledModules + +%{__cp} -r application library modules public %{buildroot}/%{sharedir}/ + +# install index.php, .htaccess +install -m0644 packages/rhel/usr/share/icingaweb/public/index.php %{buildroot}/%{sharedir}/public/index.php +install -m0644 packages/rhel/usr/share/icingaweb/public/.htaccess %{buildroot}/%{sharedir}/public/.htaccess + +# use the vagrant config for configuration for now - TODO +%{__cp} -r .vagrant-puppet/files/etc/icingaweb %{buildroot}/%{_sysconfdir}/ + +# we use the default 'icinga' database +sed -i 's/icinga2/icinga/g' %{buildroot}/%{_sysconfdir}/icingaweb/resources.ini + +# enable the monitoring module by default +ln -s %{_sysconfdir}/icingaweb/modules/monitoring %{buildroot}/%{_sysconfdir}/icingaweb/enabledModules/monitoring + +# install icingacli +install -D -m0755 bin/icingacli %{buildroot}/usr/bin/icingacli + +# install sql schema files as example + +# delete all *.in files +rm -f %{buildroot}/%{_datadir}/%{name}/public/index.php.in +rm -f %{buildroot}/%{_datadir}/%{name}/public/.htaccess.in %pre # Add apacheuser in the icingacmd group @@ -243,11 +203,9 @@ fi %files # main dirs %defattr(-,root,root) -%doc etc/schema doc README.RHEL.SUSE -%{sharedir}/application -%{sharedir}/library -%{sharedir}/public -%{sharedir}/modules +%doc etc/schema doc packages/rhel/README +%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/public +%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/modules # configs %defattr(-,root,root) %config(noreplace) %attr(-,root,root) %{apacheconfdir}/icingaweb.conf @@ -256,7 +214,14 @@ fi # logs %attr(2775,%{apacheuser},%{apachegroup}) %dir %{logdir} +%files -n php-Icinga +%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/application +%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/library + +%files -n icingacli +%attr(0755,root,root) /usr/bin/icingacli + %changelog -* Sun Oct 20 2013 Michael Friedrich - 1.0.0-1 +* Tue May 11 2014 Michael Friedrich - 0.0.1-1 - initial creation diff --git a/packages/rhel/README b/packages/rhel/README new file mode 100644 index 000000000..4e04875bb --- /dev/null +++ b/packages/rhel/README @@ -0,0 +1,57 @@ +Requirements +============ + +Disabled SELinux for sending commands via external command pipe +provided by Icinga (2) Core. + +# setenforce 0 + + +Webinterface Login +================== + +The default credentials using the internal MySQL database are + +icingaadmin:icinga + + +Internal MySQL DB Setup +======================= + +# mysql -u root -p + CREATE USER `icingaweb`@`localhost` IDENTIFIED BY 'icingaweb'; + CREATE DATABASE `icingaweb`; + GRANT ALL PRIVILEGES ON `icingaweb`.* TO `icingaweb`@`localhost`; + FLUSH PRIVILEGES; + quit + +# mysql icingaweb < /usr/share/doc/icingaweb2-*/schema/accounts.mysql.sql +# mysql icingaweb < /usr/share/doc/icingaweb2-*/schema/preferences.mysql.sql + + +Modules +======= + +The monitoring module is enabled by default. + + +Backend configuration +===================== + +/etc/icingaweb/resources.ini + +contains the database backend information. By default +the Icinga IDO DB is used by the monitoring module in + +/etc/icingaweb/modules/monitoring/backends.ini + +The external command pipe is required for sending commands +and configured for Icinga 2 in + +/etc/icingaweb/modules/monitoring/instances.ini + + +Support +======= + +Please use one of the listed support channels at https://support.icinga.org diff --git a/packages/rhel/etc/httpd/conf.d/icingaweb.conf b/packages/rhel/etc/httpd/conf.d/icingaweb.conf new file mode 100644 index 000000000..47d408a67 --- /dev/null +++ b/packages/rhel/etc/httpd/conf.d/icingaweb.conf @@ -0,0 +1,12 @@ +Alias /icingaweb /usr/share/icingaweb/public + + Options -Indexes + + AllowOverride All + + Order allow,deny + Allow from all + + EnableSendfile Off + + diff --git a/packages/rhel/usr/share/icingaweb/public/.htaccess b/packages/rhel/usr/share/icingaweb/public/.htaccess new file mode 100644 index 000000000..8588fbbe1 --- /dev/null +++ b/packages/rhel/usr/share/icingaweb/public/.htaccess @@ -0,0 +1,7 @@ +RewriteEngine on +RewriteBase /icingaweb +RewriteCond %{REQUEST_FILENAME} -s [OR] +RewriteCond %{REQUEST_FILENAME} -l [OR] +RewriteCond %{REQUEST_FILENAME} -d +RewriteRule ^.*$ - [NC,L] +RewriteRule ^.*$ index.php [NC,L] diff --git a/packages/rhel/usr/share/icingaweb/public/index.php b/packages/rhel/usr/share/icingaweb/public/index.php new file mode 100644 index 000000000..45ac69392 --- /dev/null +++ b/packages/rhel/usr/share/icingaweb/public/index.php @@ -0,0 +1,5 @@ + Date: Tue, 13 May 2014 19:38:53 +0200 Subject: [PATCH 09/55] spec: Fix enabled module symlink Refs #4075 --- icingaweb2.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icingaweb2.spec b/icingaweb2.spec index 72e5bddba..e66046a9f 100644 --- a/icingaweb2.spec +++ b/icingaweb2.spec @@ -166,7 +166,7 @@ install -m0644 packages/rhel/usr/share/icingaweb/public/.htaccess %{buildroot}/% sed -i 's/icinga2/icinga/g' %{buildroot}/%{_sysconfdir}/icingaweb/resources.ini # enable the monitoring module by default -ln -s %{_sysconfdir}/icingaweb/modules/monitoring %{buildroot}/%{_sysconfdir}/icingaweb/enabledModules/monitoring +ln -s %{sharedir}/modules/monitoring %{buildroot}/%{_sysconfdir}/icingaweb/enabledModules/monitoring # install icingacli install -D -m0755 bin/icingacli %{buildroot}/usr/bin/icingacli From e1230eb8ae15774ab892c19bfaa1b255b9713cc8 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 8 May 2014 09:42:29 +0200 Subject: [PATCH 10/55] Add style and view scripts for first prototype refs #6136 --- application/controllers/InstallController.php | 45 +++++++++ application/views/scripts/install/index.phtml | 34 +++++++ .../scripts/install/index/installog.phtml | 1 + library/Icinga/Web/StyleSheet.php | 1 + public/css/icinga/install.less | 96 +++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 application/controllers/InstallController.php create mode 100644 application/views/scripts/install/index.phtml create mode 100644 application/views/scripts/install/index/installog.phtml create mode 100644 public/css/icinga/install.less diff --git a/application/controllers/InstallController.php b/application/controllers/InstallController.php new file mode 100644 index 000000000..dee397fd0 --- /dev/null +++ b/application/controllers/InstallController.php @@ -0,0 +1,45 @@ +register(); + +use \Mockery; +use Icinga\Web\Controller\ActionController; + +class InstallController extends ActionController +{ + /** + * Whether the controller requires the user to be authenticated + * + * The install wizard has its own authentication mechanism. + * + * @var bool + */ + protected $requiresAuthentication = false; + + public function indexAction() + { + $finished = false; + $this->view->installer = 'some log info, as html'; + $this->view->wizard = Mockery::mock(); + $this->view->wizard->shouldReceive('isFinished')->andReturn($finished) + ->shouldReceive('getTitle')->andReturn('Web') + ->shouldReceive('getPages')->andReturnUsing(function () { + $a = array(Mockery::mock(array('getTitle' => 'childTest', 'getChildPages' => array( + Mockery::mock(array('getTitle' => 'child1')), + Mockery::mock(array('getTitle' => 'child2')) + ), 'isActiveChild' => false))); for ($i=0;$i<10;$i++) { $a[] = Mockery::mock(array('getTitle' => 'title'.$i, 'getChildPages' => array())); } return $a; + }) + ->shouldReceive('isActivePage')->andReturnUsing(function ($p) { return $p->getTitle() == 'title4'; }) + ->shouldReceive('isCompletedPage')->andReturnUsing(function ($p) { return $p->getTitle() < 'title4'; }) + ->shouldReceive('getActivePage')->andReturnUsing(function () { + return Mockery::mock(array('getTitle' => 'title4', '__toString' => 'teh form elements')); + }); + } +} + +// @codeCoverageIgnoreEnd diff --git a/application/views/scripts/install/index.phtml b/application/views/scripts/install/index.phtml new file mode 100644 index 000000000..13a9e587a --- /dev/null +++ b/application/views/scripts/install/index.phtml @@ -0,0 +1,34 @@ +
+
+ +

getTitle(); ?>

+
+ +
+isFinished()): ?> + partial('install/index/installog.phtml', array('installer' => $installer)); ?> + + getActivePage(); ?> + +
+
diff --git a/application/views/scripts/install/index/installog.phtml b/application/views/scripts/install/index/installog.phtml new file mode 100644 index 000000000..d4b9f7375 --- /dev/null +++ b/application/views/scripts/install/index/installog.phtml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/library/Icinga/Web/StyleSheet.php b/library/Icinga/Web/StyleSheet.php index b247f32e9..e62a861ca 100644 --- a/library/Icinga/Web/StyleSheet.php +++ b/library/Icinga/Web/StyleSheet.php @@ -22,6 +22,7 @@ class StyleSheet 'css/icinga/monitoring-colors.less', 'css/icinga/selection-toolbar.less', 'css/icinga/login.less', + 'css/icinga/install.less', ); public static function compileForPdf() diff --git a/public/css/icinga/install.less b/public/css/icinga/install.less new file mode 100644 index 000000000..421d7fdbd --- /dev/null +++ b/public/css/icinga/install.less @@ -0,0 +1,96 @@ +div.wizard { + div.header { + padding: 0.6em 0 0 1em; + height: 3em; + position: fixed; + top: 0; + left: 0; + right: 0; + + color: #eee; + background-color: #555; + background-image: linear-gradient(top, #777, #555); + background-image: -o-linear-gradient(top, #777, #555); + background-image: -ms-linear-gradient(top, #777, #555); + background-image: -webkit-linear-gradient(top, #777, #555); + + h1 { + margin: 0 3.5em; + display: inline-block; + + font-size: 2em; + } + } + + div.sidebar { + width: 13em; + position: fixed; + top: 3.6em; + left: 0; + bottom: 0; + + background-color: #999; + box-shadow: inset -0.5em 0 0.5em -0.5em #555; + -moz-box-shadow: inset -0.5em 0 0.5em -0.5em #555; + -webkit-box-shadow: inset -0.5em 0 0.5em -0.5em #555; + + & > ul { + margin: 0; + padding: 0; + list-style: none; + + & > li { + color: #f5f5f5; + font-size: 1.1em; + padding: 0.5em; + margin-left: 0.5em; + text-shadow: #555 -1px 1px 0px; + border-bottom: 1px solid #888; + + &.active { + color: black; + margin-left: 0; + padding-left: 1em; + text-shadow: none; + background-color: white; + } + + &.complete { + color: green; + } + + &.pending { + color: red; + } + + &.install { + border-bottom: 0; + } + + ul { + margin: 0; + padding: 0; + list-style: none; + + li.child { + font-size: 0.9em; + padding: 0.4em 0.8em 0; + + &.active { + font-weight: bold; + } + } + } + } + } + } + + div.panel { + padding: 1em; + position: fixed; + top: 3.6em; + left: 13em; + right: 0; + bottom: 0; + } +} From 4cf5fe6fddd155c4bb5fd7ed9014c0f953f2b658 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 13 May 2014 14:24:51 +0200 Subject: [PATCH 11/55] Add multistep form refs #6136 --- application/controllers/InstallController.php | 98 ++++- application/views/scripts/install/index.phtml | 18 +- library/Icinga/Web/Wizard/Page.php | 54 +++ library/Icinga/Web/Wizard/Wizard.php | 379 ++++++++++++++++++ 4 files changed, 522 insertions(+), 27 deletions(-) create mode 100644 library/Icinga/Web/Wizard/Page.php create mode 100644 library/Icinga/Web/Wizard/Wizard.php diff --git a/application/controllers/InstallController.php b/application/controllers/InstallController.php index dee397fd0..f2b0398e2 100644 --- a/application/controllers/InstallController.php +++ b/application/controllers/InstallController.php @@ -3,11 +3,9 @@ // {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}} -require_once 'Mockery/Loader.php'; -$mockeryLoader = new \Mockery\Loader; -$mockeryLoader->register(); - -use \Mockery; +use Icinga\Web\Session; +use Icinga\Web\Wizard\Page; +use Icinga\Web\Wizard\Wizard; use Icinga\Web\Controller\ActionController; class InstallController extends ActionController @@ -21,24 +19,82 @@ class InstallController extends ActionController */ protected $requiresAuthentication = false; + /** + * Show the wizard and run the installation once its finished + */ public function indexAction() { - $finished = false; - $this->view->installer = 'some log info, as html'; - $this->view->wizard = Mockery::mock(); - $this->view->wizard->shouldReceive('isFinished')->andReturn($finished) - ->shouldReceive('getTitle')->andReturn('Web') - ->shouldReceive('getPages')->andReturnUsing(function () { - $a = array(Mockery::mock(array('getTitle' => 'childTest', 'getChildPages' => array( - Mockery::mock(array('getTitle' => 'child1')), - Mockery::mock(array('getTitle' => 'child2')) - ), 'isActiveChild' => false))); for ($i=0;$i<10;$i++) { $a[] = Mockery::mock(array('getTitle' => 'title'.$i, 'getChildPages' => array())); } return $a; - }) - ->shouldReceive('isActivePage')->andReturnUsing(function ($p) { return $p->getTitle() == 'title4'; }) - ->shouldReceive('isCompletedPage')->andReturnUsing(function ($p) { return $p->getTitle() < 'title4'; }) - ->shouldReceive('getActivePage')->andReturnUsing(function () { - return Mockery::mock(array('getTitle' => 'title4', '__toString' => 'teh form elements')); - }); + $wizard = $this->createWizard(); + $wizard->navigate(); // Needs to be called before isSubmittedAndValid() as this creates the form + + if ($wizard->isSubmittedAndValid() && $wizard->isFinished()) { + // TODO: Run the installer (Who creates an installer? How do we handle module installers?) + $this->dropConfiguration(); // TODO: Should only be done if the installation has been successfully completed + $this->view->installer = ''; + } else { + $this->storeConfiguration($wizard->getConfig()); + } + + $this->view->wizard = $wizard; + } + + /** + * Create the wizard and register all pages + * + * @return Wizard + */ + protected function createWizard() + { + $wizard = new Wizard(); + $wizard->setTitle('Web'); + $wizard->setRequest($this->getRequest()); + $wizard->setConfiguration($this->loadConfiguration()); + $wizard->addPages( + array( + '1st step' => new Page(), + '2nd step' => new Page(), + '3rd step' => new Page(), + 'a wizard' => array( + '4th step' => new Page(), + '5th step' => new Page() + ), + 'last step' => new Page() + ) + ); + + return $wizard; + } + + /** + * Store the given configuration values + * + * @param Zend_Config $config The configuration + */ + protected function storeConfiguration(Zend_Config $config) + { + $session = Session::getSession(); + $session->getNamespace('WebWizard')->setAll($config->toArray(), true); + $session->write(); + } + + /** + * Load all configuration values + * + * @return Zend_Config + */ + protected function loadConfiguration() + { + return new Zend_Config(Session::getSession()->getNamespace('WebWizard')->getAll(), true); + } + + /** + * Clear all stored configuration values + */ + protected function dropConfiguration() + { + $session = Session::getSession(); + $session->removeNamespace('WebWizard'); + $session->write(); } } diff --git a/application/views/scripts/install/index.phtml b/application/views/scripts/install/index.phtml index 13a9e587a..baf0608f0 100644 --- a/application/views/scripts/install/index.phtml +++ b/application/views/scripts/install/index.phtml @@ -6,17 +6,23 @@ diff --git a/library/Icinga/Web/Wizard/Page.php b/library/Icinga/Web/Wizard/Page.php new file mode 100644 index 000000000..ae839d58a --- /dev/null +++ b/library/Icinga/Web/Wizard/Page.php @@ -0,0 +1,54 @@ +title = $title; + } + + /** + * Return the title of this wizard page + * + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Return a config containing all values of this wizard page + * + * @return Zend_Config + */ + public function getConfig() + { + return $this->getConfiguration(); + } +} diff --git a/library/Icinga/Web/Wizard/Wizard.php b/library/Icinga/Web/Wizard/Wizard.php new file mode 100644 index 000000000..6efba7665 --- /dev/null +++ b/library/Icinga/Web/Wizard/Wizard.php @@ -0,0 +1,379 @@ +pages; + } + + /** + * Add a new page to this wizard + * + * @param Page $page The page to add + */ + public function addPage(Page $page) + { + $ident = $this->generatePageIdentifier($page); + $wizardConfig = $this->getConfig(); + if ($wizardConfig->get($ident) === null) { + $wizardConfig->{$ident} = new Zend_Config(array(), true); + } + + $page->setTokenDisabled(); // Usually default for pages, but not for wizards + $page->setConfiguration($wizardConfig->{$ident}); + $page->setRequest($this->getRequest()); + $page->setName($ident); + $this->pages[] = $page; + } + + /** + * Add multiple pages to this wizard + * + * The given array's keys are titles and its values are class names to add + * as wizard pages. An array as value causes a sub-wizard being added. + * + * @param array $pages The pages to add to the wizard + */ + public function addPages(array $pages) + { + foreach ($pages as $title => $pageClassOrArray) { + if (is_array($pageClassOrArray)) { + $wizard = new static(); + $wizard->setTitle($title); + $this->addPage($wizard); + $wizard->addPages($pageClassOrArray); + } elseif (is_string($pageClassOrArray)) { + $page = new $pageClassOrArray(); + $page->setTitle($title); + $this->addPage($page); + } else { + $pageClassOrArray->setTitle($title); + $this->addPage($pageClassOrArray); + } + } + } + + /** + * Return this wizard's progress + * + * @param int $default The step to return in case this wizard has no progress information yet + * + * @return int The current step + */ + public function getProgress($default = 0) + { + return $this->getConfig()->get('progress', $default); + } + + /** + * Set this wizard's progress + * + * @param int $step The current step + */ + public function setProgress($step) + { + $config = $this->getConfig(); + $config->progress = $step; + } + + /** + * Return the current page + * + * @return Page + * + * @throws ProgrammingError In case there are not any pages registered + */ + public function getCurrentPage() + { + $pages = $this->getPages(); + + if (empty($pages)) { + throw new ProgrammingError('This wizard has no pages'); + } + + return $pages[$this->getProgress()]; + } + + /** + * Return whether the given page is the current page + * + * @param Page $page The page to check + * + * @return bool + */ + public function isCurrentPage(Page $page) + { + return $this->getCurrentPage() === $page; + } + + /** + * Return whether the given page is the first page in the wizard + * + * @param Page $page The page to check + * + * @return bool + * + * @throws ProgrammingError In case there are not any pages registered + */ + public function isFirstPage(Page $page) + { + $pages = $this->getPages(); + + if (empty($pages)) { + throw new ProgrammingError('This wizard has no pages'); + } + + return $pages[0] === $page; + } + + /** + * Return whether the given page has been completed + * + * @param Page $page The page to check + * + * @return bool + * + * @throws ProgrammingError In case there are not any pages registered + */ + public function isCompletedPage(Page $page) + { + $pages = $this->getPages(); + + if (empty($pages)) { + throw new ProgrammingError('This wizard has no pages'); + } + + return $this->isFinished() || array_search($page, $pages, true) < $this->getProgress(); + } + + /** + * Return whether the given page is the last page in the wizard + * + * @param Page $page The page to check + * + * @return bool + * + * @throws ProgrammingError In case there are not any pages registered + */ + public function isLastPage(Page $page) + { + $pages = $this->getPages(); + + if (empty($pages)) { + throw new ProgrammingError('This wizard has no pages'); + } + + return $pages[count($pages) - 1] === $page; + } + + /** + * Return whether this wizard has been completed + * + * @return bool + */ + public function isFinished() + { + return $this->finished && $this->isLastPage($this->getCurrentPage()); + } + + /** + * Return whether the given page is a wizard + * + * @param Page $page The page to check + * + * @return bool + */ + public function isWizard(Page $page) + { + return $page instanceof self; + } + + /** + * Return whether either the back- or next-button was clicked + * + * @see Form::isSubmitted() + */ + public function isSubmitted() + { + $checkData = $this->getRequest()->getParams(); + return isset($checkData['btn_return']) || isset($checkData['btn_advance']); + } + + /** + * Update the wizard's progress + * + * @param bool $lastStepIsLast Whether the last step of this wizard is actually the very last one + */ + public function navigate($lastStepIsLast = true) + { + $currentPage = $this->getCurrentPage(); + if (($pageName = $this->getRequest()->getParam('btn_advance'))) { + if (!$this->isWizard($currentPage) || $currentPage->navigate(false) || $currentPage->isFinished()) { + if ($this->isLastPage($currentPage) && (!$lastStepIsLast || $pageName === 'install')) { + $this->finished = true; + } else { + $pages = $this->getPages(); + $newStep = $this->getProgress() + 1; + if (isset($pages[$newStep]) && $pages[$newStep]->getName() === $pageName) { + $this->setProgress($newStep); + } + } + } + } elseif (($pageName = $this->getRequest()->getParam('btn_return'))) { + if ($this->isWizard($currentPage) && $currentPage->getProgress() > 0) { + $currentPage->navigate(false); + } elseif (!$this->isFirstPage($currentPage)) { + $pages = $this->getPages(); + $newStep = $this->getProgress() - 1; + if ($pages[$newStep]->getName() === $pageName) { + $this->setProgress($newStep); + } + } + } + + $config = $this->getConfig(); + $config->{$currentPage->getName()} = $currentPage->getConfig(); + } + + /** + * Return a unique identifier for the given page + * + * @param Page $page The page for which to return the identifier + * + * @return string The page's unique identifier + */ + protected function generatePageIdentifier(Page $page) + { + if (($name = $page->getName())) { + return $name; + } + + $pageClass = get_class($page); + $wizardConfig = $this->getConfig(); + + if ($wizardConfig->get('page_names') === null || $wizardConfig->page_names->get($pageClass) === null) { + $wizardConfig->page_names = $wizardConfig->get('page_names', new Zend_Config(array(), true)); + $wizardConfig->page_names->{$pageClass} = sprintf('%06x', mt_rand(0, 0xffffff)); + } + + return $wizardConfig->page_names->{$pageClass}; + } + + /** + * Setup the current wizard page + */ + protected function create() + { + $currentPage = $this->getCurrentPage(); + if ($this->isWizard($currentPage)) { + $this->createWizard($currentPage); + } else { + $this->createPage($currentPage); + } + } + + /** + * Display the given page as this wizard's current page + * + * @param Page $page The page + */ + protected function createPage(Page $page) + { + $pages = $this->getPages(); + $currentStep = $this->getProgress(); + + $this->addSubForm($page, $page->getName()); + + if (!$this->isFirstPage($page)) { + $this->addElement( + 'button', + 'btn_return', + array( + 'type' => 'submit', + 'label' => t('Previous'), + 'value' => $pages[$currentStep - 1]->getName() + ) + ); + } + + $this->addElement( + 'button', + 'btn_advance', + array( + 'type' => 'submit', + 'label' => $this->isLastPage($page) ? t('Install') : t('Next'), + 'value' => $this->isLastPage($page) ? 'install' : $pages[$currentStep + 1]->getName() + ) + ); + } + + /** + * Display the current page of the given wizard as this wizard's current page + * + * @param Wizard $wizard The wizard + */ + protected function createWizard(Wizard $wizard) + { + $isFirstPage = $this->isFirstPage($wizard); + $isLastPage = $this->isLastPage($wizard); + $currentSubPage = $wizard->getCurrentPage(); + $isFirstSubPage = $wizard->isFirstPage($currentSubPage); + $isLastSubPage = $wizard->isLastPage($currentSubPage); + + $this->addSubForm($currentSubPage, $currentSubPage->getName()); + + if (!$isFirstPage || !$isFirstSubPage) { + $pages = $isFirstSubPage ? $this->getPages() : $wizard->getPages(); + $currentStep = $isFirstSubPage ? $this->getProgress() : $wizard->getProgress(); + $this->addElement( + 'button', + 'btn_return', + array( + 'type' => 'submit', + 'label' => t('Previous'), + 'value' => $pages[$currentStep - 1]->getName() + ) + ); + } + + $pages = $isLastSubPage ? $this->getPages() : $wizard->getPages(); + $currentStep = $isLastSubPage ? $this->getProgress() : $wizard->getProgress(); + $this->addElement( + 'button', + 'btn_advance', + array( + 'type' => 'submit', + 'label' => $isLastPage && $isLastSubPage ? t('Install') : t('Next'), + 'value' => $isLastPage && $isLastSubPage ? 'install' : $pages[$currentStep + 1]->getName() + ) + ); + } +} From 88e451402f3c369ef19e84603021e33f2888fcc1 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 13 May 2014 14:27:30 +0200 Subject: [PATCH 12/55] Redirect to /install when the setup.token exists but no config.ini refs #6136 --- application/controllers/InstallController.php | 9 +++ .../Web/Controller/ActionController.php | 64 ++++++++++++++----- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/application/controllers/InstallController.php b/application/controllers/InstallController.php index f2b0398e2..f476a568e 100644 --- a/application/controllers/InstallController.php +++ b/application/controllers/InstallController.php @@ -19,6 +19,15 @@ class InstallController extends ActionController */ protected $requiresAuthentication = false; + /** + * Whether the controller requires configuration + * + * The install wizard does not require any configuration. + * + * @var bool + */ + protected $requiresConfiguration = false; + /** * Show the wizard and run the installation once its finished */ diff --git a/library/Icinga/Web/Controller/ActionController.php b/library/Icinga/Web/Controller/ActionController.php index 5b42f8730..5893a3c3f 100644 --- a/library/Icinga/Web/Controller/ActionController.php +++ b/library/Icinga/Web/Controller/ActionController.php @@ -46,6 +46,7 @@ use Icinga\File\Pdf; use Icinga\Exception\ProgrammingError; use Icinga\Web\Session; use Icinga\Session\SessionNamespace; +use Icinga\Exception\NotReadableError; /** * Base class for all core action controllers @@ -61,6 +62,13 @@ class ActionController extends Zend_Controller_Action */ protected $requiresAuthentication = true; + /** + * Whether the controller requires configuration + * + * @var bool + */ + protected $requiresConfiguration = true; + private $config; private $configs = array(); @@ -114,26 +122,24 @@ class ActionController extends Zend_Controller_Action $this->_helper = new Zend_Controller_Action_HelperBroker($this); $this->_helper->addPath('../application/controllers/helpers'); - // when noInit is set (e.g. for testing), authentication and init is skipped - if (isset($invokeArgs['noInit'])) { - // TODO: Find out whether this still makes sense? - return; - } - if ($this->_request->isXmlHttpRequest()) { $this->windowId = $this->_request->getHeader('X-Icinga-WindowId', null); } - if ($this->requiresLogin() === false) { - $this->view->tabs = new Tabs(); - $this->init(); - } else { - $url = $this->getRequestUrl(); - if ($url === 'default/index/index') { - // TODO: We need our own router :p - $url = 'dashboard'; + if ($this->requiresConfig() === false) { + if ($this->requiresLogin() === false) { + $this->view->tabs = new Tabs(); + $this->init(); + } else { + $url = $this->getRequestUrl(); + if ($url === 'default/index/index') { + // TODO: We need our own router :p + $url = 'dashboard'; + } + $this->redirectToLogin($url); } - $this->redirectToLogin($url); + } else { + $this->redirectNow(Url::fromPath('install')); } } @@ -224,11 +230,39 @@ class ActionController extends Zend_Controller_Action } } + /** + * Check whether the controller requires configuration. That is when no configuration + * is available and when it is possible to setup the configuration + * + * @return bool + * + * @see requiresConfiguration + */ + protected function requiresConfig() + { + if (!$this->requiresConfiguration) { + return false; + } + + if (file_exists(Config::$configDir . '/setup.token')) { + try { + $config = Config::app()->toArray(); + } catch (NotReadableError $e) { + return true; + } + + return empty($config); + } else { + return false; + } + } + /** * Check whether the controller requires a login. That is when the controller requires authentication and the * user is currently not authenticated * * @return bool + * * @see requiresAuthentication */ protected function requiresLogin() From de169c7bf58ca62285787473b2f60d23de56e5b3 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 13 May 2014 14:32:08 +0200 Subject: [PATCH 13/55] Make it possible to disable form submit buttons forcefully --- library/Icinga/Web/Form.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 7cd3ad746..384ca0848 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -127,6 +127,15 @@ class Form extends Zend_Form */ protected $last_note_id = 0; + /** + * Whether buttons are shown or not + * + * This is just a q&d solution and MUST NOT survive any refactoring! + * + * @var bool + */ + protected $buttonsHidden = false; + /** * Getter for the session ID * @@ -279,11 +288,11 @@ class Form extends Zend_Form $this->initCsrfToken(); $this->create(); - if ($this->submitLabel) { + if (!$this->buttonsHidden && $this->submitLabel) { $this->addSubmitButton(); } - if ($this->cancelLabel) { + if (!$this->buttonsHidden && $this->cancelLabel) { $this->addCancelButton(); } @@ -596,4 +605,9 @@ class Form extends Zend_Form return $this; } + + public function hideButtons() + { + $this->buttonsHidden = true; + } } From 51bac035ac1bdee2c63f680ec66120beb1081af3 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 13 May 2014 15:28:27 +0200 Subject: [PATCH 14/55] Fix subForm functionality --- library/Icinga/Web/Form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 384ca0848..3822062e0 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -599,7 +599,7 @@ class Form extends Zend_Form $decorators = $this->getDecorators(); if (empty($decorators)) { $this->addDecorator('FormElements') - //->addDecorator('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form')) + ->addDecorator('HtmlTag', array('tag' => 'div')) // Quickfix to get subForms to work ->addDecorator('Form'); } From 429e09aae2e9f8fd63dfad1e5e16b0e22f90dfdc Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 14 May 2014 09:01:24 +0200 Subject: [PATCH 15/55] Multistep pages should not have random generated names refs #6136 --- application/controllers/InstallController.php | 31 +++++++------- library/Icinga/Web/Wizard/Page.php | 8 ++++ library/Icinga/Web/Wizard/Wizard.php | 40 +++++-------------- 3 files changed, 33 insertions(+), 46 deletions(-) diff --git a/application/controllers/InstallController.php b/application/controllers/InstallController.php index f476a568e..9755f99d7 100644 --- a/application/controllers/InstallController.php +++ b/application/controllers/InstallController.php @@ -4,7 +4,6 @@ // {{{ICINGA_LICENSE_HEADER}}} use Icinga\Web\Session; -use Icinga\Web\Wizard\Page; use Icinga\Web\Wizard\Wizard; use Icinga\Web\Controller\ActionController; @@ -36,12 +35,14 @@ class InstallController extends ActionController $wizard = $this->createWizard(); $wizard->navigate(); // Needs to be called before isSubmittedAndValid() as this creates the form - if ($wizard->isSubmittedAndValid() && $wizard->isFinished()) { - // TODO: Run the installer (Who creates an installer? How do we handle module installers?) - $this->dropConfiguration(); // TODO: Should only be done if the installation has been successfully completed - $this->view->installer = ''; - } else { - $this->storeConfiguration($wizard->getConfig()); + if ($wizard->isSubmittedAndValid()) { + if ($wizard->isFinished()) { + // TODO: Run the installer (Who creates an installer? How do we handle module installers?) + $this->dropConfiguration(); // TODO: Should only be done if the installation has been successfully completed + $this->view->installer = ''; + } else { + $this->storeConfiguration($wizard->getConfig()); + } } $this->view->wizard = $wizard; @@ -60,14 +61,14 @@ class InstallController extends ActionController $wizard->setConfiguration($this->loadConfiguration()); $wizard->addPages( array( - '1st step' => new Page(), - '2nd step' => new Page(), - '3rd step' => new Page(), - 'a wizard' => array( - '4th step' => new Page(), - '5th step' => new Page() - ), - 'last step' => new Page() +// t('Welcome') => 'Icinga\Form\Install\WelcomePage', +// t('Requirements') => 'Icinga\Form\Install\RequirementsPage', +// t('Authentication') => 'Icinga\Form\Install\AuthenticationPage', +// t('Administration') => 'Icinga\Form\Install\AdministrationPage', +// t('Preferences') => 'Icinga\Form\Install\PreferencesPage', + t('Logging') => 'Icinga\Form\Install\LoggingPage', +// t('Database Setup') => 'Icinga\Form\Install\DatabasePage', +// t('Summary') => 'Icinga\Form\Install\SummaryPage' ) ); diff --git a/library/Icinga/Web/Wizard/Page.php b/library/Icinga/Web/Wizard/Page.php index ae839d58a..53383fd1a 100644 --- a/library/Icinga/Web/Wizard/Page.php +++ b/library/Icinga/Web/Wizard/Page.php @@ -22,6 +22,14 @@ class Page extends Form */ protected $title = ''; + /** + * Overwrite this to initialize this wizard page + */ + public function init() + { + + } + /** * Set the title for this wizard page * diff --git a/library/Icinga/Web/Wizard/Wizard.php b/library/Icinga/Web/Wizard/Wizard.php index 6efba7665..301149f08 100644 --- a/library/Icinga/Web/Wizard/Wizard.php +++ b/library/Icinga/Web/Wizard/Wizard.php @@ -41,16 +41,18 @@ class Wizard extends Page */ public function addPage(Page $page) { - $ident = $this->generatePageIdentifier($page); - $wizardConfig = $this->getConfig(); - if ($wizardConfig->get($ident) === null) { - $wizardConfig->{$ident} = new Zend_Config(array(), true); + if (!($pageName = $page->getName())) { + throw new ProgrammingError('Wizard page "' . get_class($page) . '" has no unique name'); } - $page->setTokenDisabled(); // Usually default for pages, but not for wizards - $page->setConfiguration($wizardConfig->{$ident}); + $wizardConfig = $this->getConfig(); + if ($wizardConfig->get($pageName) === null) { + $wizardConfig->{$pageName} = new Zend_Config(array(), true); + } + + $page->setConfiguration($wizardConfig->{$pageName}); $page->setRequest($this->getRequest()); - $page->setName($ident); + $page->setTokenDisabled(); // Usually default for pages, but not for wizards $this->pages[] = $page; } @@ -263,30 +265,6 @@ class Wizard extends Page $config->{$currentPage->getName()} = $currentPage->getConfig(); } - /** - * Return a unique identifier for the given page - * - * @param Page $page The page for which to return the identifier - * - * @return string The page's unique identifier - */ - protected function generatePageIdentifier(Page $page) - { - if (($name = $page->getName())) { - return $name; - } - - $pageClass = get_class($page); - $wizardConfig = $this->getConfig(); - - if ($wizardConfig->get('page_names') === null || $wizardConfig->page_names->get($pageClass) === null) { - $wizardConfig->page_names = $wizardConfig->get('page_names', new Zend_Config(array(), true)); - $wizardConfig->page_names->{$pageClass} = sprintf('%06x', mt_rand(0, 0xffffff)); - } - - return $wizardConfig->page_names->{$pageClass}; - } - /** * Setup the current wizard page */ From 1637a19c237872ad81c6b068afa9c2a09a73c302 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 14 May 2014 11:01:01 +0200 Subject: [PATCH 16/55] Fix multistep form creation refs #6136 --- application/controllers/InstallController.php | 2 +- library/Icinga/Web/Wizard/Wizard.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/application/controllers/InstallController.php b/application/controllers/InstallController.php index 9755f99d7..da320a6b1 100644 --- a/application/controllers/InstallController.php +++ b/application/controllers/InstallController.php @@ -33,9 +33,9 @@ class InstallController extends ActionController public function indexAction() { $wizard = $this->createWizard(); - $wizard->navigate(); // Needs to be called before isSubmittedAndValid() as this creates the form if ($wizard->isSubmittedAndValid()) { + $wizard->navigate(); if ($wizard->isFinished()) { // TODO: Run the installer (Who creates an installer? How do we handle module installers?) $this->dropConfiguration(); // TODO: Should only be done if the installation has been successfully completed diff --git a/library/Icinga/Web/Wizard/Wizard.php b/library/Icinga/Web/Wizard/Wizard.php index 301149f08..2129dac79 100644 --- a/library/Icinga/Web/Wizard/Wizard.php +++ b/library/Icinga/Web/Wizard/Wizard.php @@ -288,6 +288,7 @@ class Wizard extends Page $pages = $this->getPages(); $currentStep = $this->getProgress(); + $page->buildForm(); // Needs to get called manually as it's nothing that Zend knows about $this->addSubForm($page, $page->getName()); if (!$this->isFirstPage($page)) { @@ -326,6 +327,7 @@ class Wizard extends Page $isFirstSubPage = $wizard->isFirstPage($currentSubPage); $isLastSubPage = $wizard->isLastPage($currentSubPage); + $currentSubPage->buildForm(); // Needs to get called manually as it's nothing that Zend knows about $this->addSubForm($currentSubPage, $currentSubPage->getName()); if (!$isFirstPage || !$isFirstSubPage) { From 33d41426643595e8f1beb1ea5ab94e0c0c33727d Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 14 May 2014 11:02:11 +0200 Subject: [PATCH 17/55] Make it possible to recreate a form --- library/Icinga/Web/Form.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 3822062e0..5d5c3da85 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -610,4 +610,13 @@ class Form extends Zend_Form { $this->buttonsHidden = true; } + + /** + * q&d solution to be able to recreate a form + */ + public function reset() + { + $this->created = false; + $this->clearElements(); + } } From 1f942acd38a4ef5a1655cc17badc639aecbe2d24 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 14 May 2014 11:03:16 +0200 Subject: [PATCH 18/55] Fix multistep page creation refs #6136 --- library/Icinga/Web/Wizard/Wizard.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/Icinga/Web/Wizard/Wizard.php b/library/Icinga/Web/Wizard/Wizard.php index 2129dac79..6be831ae8 100644 --- a/library/Icinga/Web/Wizard/Wizard.php +++ b/library/Icinga/Web/Wizard/Wizard.php @@ -246,6 +246,7 @@ class Wizard extends Page $newStep = $this->getProgress() + 1; if (isset($pages[$newStep]) && $pages[$newStep]->getName() === $pageName) { $this->setProgress($newStep); + $this->reset(); } } } @@ -257,6 +258,7 @@ class Wizard extends Page $newStep = $this->getProgress() - 1; if ($pages[$newStep]->getName() === $pageName) { $this->setProgress($newStep); + $this->reset(); } } } From 754f854dd03c381a40d79210a8a3e9ac34caddd0 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 14 May 2014 12:42:22 +0200 Subject: [PATCH 19/55] Multistep pages should know about their multistep form refs #6136 --- library/Icinga/Web/Wizard/Page.php | 19 ++++++++++++++++++ library/Icinga/Web/Wizard/Wizard.php | 30 ++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/library/Icinga/Web/Wizard/Page.php b/library/Icinga/Web/Wizard/Page.php index 53383fd1a..fdc0fd171 100644 --- a/library/Icinga/Web/Wizard/Page.php +++ b/library/Icinga/Web/Wizard/Page.php @@ -15,6 +15,13 @@ class Page extends Form */ protected $tokenDisabled = true; + /** + * The wizard this page is part of + * + * @var Wizard + */ + protected $wizard; + /** * The title of this wizard page * @@ -22,6 +29,18 @@ class Page extends Form */ protected $title = ''; + /** + * Create a new wizard page + * + * @param Wizard $wizard The wizard this page is part of + * @param mixed $options Zend_Form options + */ + public function __construct(Wizard $wizard = null, $options = null) + { + parent::__construct($options); + $this->wizard = $wizard; + } + /** * Overwrite this to initialize this wizard page */ diff --git a/library/Icinga/Web/Wizard/Wizard.php b/library/Icinga/Web/Wizard/Wizard.php index 6be831ae8..64e9e5f24 100644 --- a/library/Icinga/Web/Wizard/Wizard.php +++ b/library/Icinga/Web/Wizard/Wizard.php @@ -34,6 +34,27 @@ class Wizard extends Page return $this->pages; } + /** + * Return a page by its name or null if it's not found + * + * @param string $pageName The name of the page + * + * @return Page|null + */ + public function getPage($pageName) + { + $candidates = array_filter( + $this->pages, // Cannot use getPages() here because I might get called as part of Page::isRequired() + function ($page) use ($pageName) { return $page->getName() === $pageName; } + ); + + if (!empty($candidates)) { + return array_shift($candidates); + } elseif ($this->wizard !== null) { + return $this->wizard->getPage($pageName); + } + } + /** * Add a new page to this wizard * @@ -68,17 +89,14 @@ class Wizard extends Page { foreach ($pages as $title => $pageClassOrArray) { if (is_array($pageClassOrArray)) { - $wizard = new static(); + $wizard = new static($this); $wizard->setTitle($title); $this->addPage($wizard); $wizard->addPages($pageClassOrArray); - } elseif (is_string($pageClassOrArray)) { - $page = new $pageClassOrArray(); + } else { + $page = new $pageClassOrArray($this); $page->setTitle($title); $this->addPage($page); - } else { - $pageClassOrArray->setTitle($title); - $this->addPage($pageClassOrArray); } } } From ef7bb0e79485976d3321b0885ab60743c715b4cd Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 14 May 2014 12:44:12 +0200 Subject: [PATCH 20/55] It is a multistep page's responsibility whether it is shown to the user refs #6136 --- library/Icinga/Web/Wizard/Page.php | 14 +++++++++++++- library/Icinga/Web/Wizard/Wizard.php | 8 +++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/library/Icinga/Web/Wizard/Page.php b/library/Icinga/Web/Wizard/Page.php index fdc0fd171..82e064745 100644 --- a/library/Icinga/Web/Wizard/Page.php +++ b/library/Icinga/Web/Wizard/Page.php @@ -49,6 +49,18 @@ class Page extends Form } + /** + * Return whether this page needs to be shown to the user + * + * Overwrite this to add page specific handling + * + * @return bool + */ + public function isRequired() + { + return true; + } + /** * Set the title for this wizard page * @@ -70,7 +82,7 @@ class Page extends Form } /** - * Return a config containing all values of this wizard page + * Return a config containing all values provided by the user * * @return Zend_Config */ diff --git a/library/Icinga/Web/Wizard/Wizard.php b/library/Icinga/Web/Wizard/Wizard.php index 64e9e5f24..3fc5fa49d 100644 --- a/library/Icinga/Web/Wizard/Wizard.php +++ b/library/Icinga/Web/Wizard/Wizard.php @@ -8,6 +8,12 @@ use Zend_Config; use Icinga\Web\Form; use Icinga\Exception\ProgrammingError; +/** + * Multistep form with support for nesting and dynamic behaviour + * + * @todo Pages that were displayed initially and filled out by the user remain + * currently in the configuration returned by Wizard::getConfig() + */ class Wizard extends Page { /** @@ -31,7 +37,7 @@ class Wizard extends Page */ public function getPages() { - return $this->pages; + return array_filter($this->pages, function ($page) { return $page->isRequired(); }); } /** From 709146d49f18e92973189c985862083c0acec0ac Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 14 May 2014 13:20:21 +0200 Subject: [PATCH 21/55] Add wizard page for the logging configuration resolves #6129 --- application/forms/Install/LoggingPage.php | 67 +++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 application/forms/Install/LoggingPage.php diff --git a/application/forms/Install/LoggingPage.php b/application/forms/Install/LoggingPage.php new file mode 100644 index 000000000..6bb4a21ce --- /dev/null +++ b/application/forms/Install/LoggingPage.php @@ -0,0 +1,67 @@ +setName('logging'); + } + + /** + * Create and return the logging form + * + * @return LoggingForm + */ + protected function createForm() + { + if ($this->loggingForm === null) { + $this->loggingForm = new LoggingForm(); + $this->loggingForm->hideButtons(); + $this->loggingForm->setTokenDisabled(); + $this->loggingForm->setRequest($this->getRequest()); + $this->loggingForm->setConfiguration($this->getConfiguration()); + } + + return $this->loggingForm; + } + + /** + * Create this wizard page + */ + protected function create() + { + $loggingForm = $this->createForm(); + $loggingForm->buildForm(); // Needs to get called manually as it's nothing that Zend knows about + $this->addSubForm($loggingForm, $loggingForm->getName()); + } + + /** + * Return a config containing all values provided by the user + * + * @return Zend_Config + */ + public function getConfig() + { + return $this->createForm()->getConfig(); + } +} +// @codeCoverageIgnoreEnd From f6d42944f7ce296aac53e5d669800329c024ac06 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Wed, 14 May 2014 17:45:40 +0200 Subject: [PATCH 22/55] Update Vagrant Icinga 2 test config refs #6127 --- .../files/etc/icinga2/conf.d/test-config.conf | 131 +++++------------- 1 file changed, 35 insertions(+), 96 deletions(-) diff --git a/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf b/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf index ee13a0ebb..412307328 100644 --- a/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf +++ b/.vagrant-puppet/files/etc/icinga2/conf.d/test-config.conf @@ -1,5 +1,4 @@ - -template CheckCommand "dummy-host-generic" { +object CheckCommand "dummy-host" { import "plugin-check-command" command = [ PluginDir + "/libexec/test_hostcheck.pl" ] arguments = { @@ -17,7 +16,7 @@ template CheckCommand "dummy-host-generic" { vars.check_hostname = "$name$" } -template CheckCommand "dummy-service-generic" { +object CheckCommand "dummy-service" { import "plugin-check-command" command = [ PluginDir + "/libexec/test_servicecheck.pl" ] arguments = { @@ -40,119 +39,59 @@ template CheckCommand "dummy-service-generic" { vars.check_servicedesc = "$service.name$" } -// Concrete check commands -object CheckCommand "dummy-host" { - import "dummy-host-generic" -} - -object CheckCommand "dummy-service" { - import "dummy-service-generic" -} - // Hostgroups object HostGroup "all-hosts" { display_name = "All hosts on the system" assign where true } -object HostGroup "all-ok" { - display_name = "All ok hosts" - assign where regex("^test-ok", host.name) +host_types = ["ok", "random", "down", "up", "unreachable", "pending"] + +__for (host_type in host_types) { + object HostGroup "all-" + host_type { + display_name = "All " + host_type + " hosts" + assign where regex("^test-" + host_type, host.name) + } } -object HostGroup "all-chaos" { - display_name = "All chaos hosts" - assign where regex("^test-random", host.name) -} - -object HostGroup "all-down" { - display_name = "All down hosts" - assign where regex("^test-down", host.name) -} - -object HostGroup "all-up" { - display_name = "All ok hosts" - assign where regex("^test-ok", host.name) -} - -object HostGroup "all-unreachable" { - display_name = "All ok hosts" - assign where regex("^test-unreachable", host.name) -} - -object HostGroup "all-pending" { - display_name = "All ok hosts" - assign where regex("^test-pending", host.name) -} +service_types = ["ok", "warning", "critical", "unknown", "flapping", "pending"] // Servicegroups -object ServiceGroup "service-ok" { - display_name = "All ok services" - assign where regex("^service-ok", service.name) -} - -object ServiceGroup "service-warning" { - display_name = "All warning services" - assign where regex("^service-warning", service.name) -} - -object ServiceGroup "service-critical" { - display_name = "All critical services" - assign where regex("^service-critical", service.name) -} - -object ServiceGroup "service-unknown" { - display_name = "All unknown services" - assign where regex("^service-unknown", service.name) -} - -object ServiceGroup "service-flapping" { - display_name = "All flapping services" - assign where regex("^service-flapping", service.name) -} - - -object ServiceGroup "service-pending" { - display_name = "All pending services" - assign where regex("^service-pending", service.name) -} - -// Config helper -function loop(count, func) { - count == 1 || loop(count - 1, func) - func(count) +__for (service_type in service_types) { + object ServiceGroup "service-" + service_type { + display_name = "All " + service_type + " services" + assign where regex("^service-" + service_type, service.name) + } } // --------------------------------------------------------------------------------------------------------------------- // Services // --------------------------------------------------------------------------------------------------------------------- -function createService(filter, num, checkEnabled) { - apply Service "service-" + filter + "-" + string(num) { +__function createService(service_type, num) { + apply Service "service-" + service_type + "-" + string(num + 1) { import "generic-service" - check_command = "dummy-service" - enable_active_checks = checkEnabled - vars.check_type = filter - assign where match("*" + filter + "*", host.vars.check_config) + + check_command = "dummy-service" + enable_active_checks = (service_type != "pending") + vars.check_type = service_type + + assign where match("*" + service_type + "*", host.vars.check_config) } } -loop(4, lambda num: { - createService("ok", num, true) - createService("warning", num, true) - createService("critical", num, true) - createService("flap", num, true) - createService("random", num, true) - createService("unknown", num, true) - createService("pending", num, false) -}) +__for (num in range(4)) { + __for (service_type in service_types) { + createService(service_type, num) + } +} // --------------------------------------------------------------------------------------------------------------------- // Hosts // --------------------------------------------------------------------------------------------------------------------- -function createHost(checkType, checkConfig, num, checkEnabled) { - object Host "test-" + checkType + "-" + string(num) { +__function createHost(checkType, checkConfig, num, checkEnabled) { + object Host "test-" + checkType + "-" + string(num + 1) { import "generic-host" address = "127.0.0.1" check_command = "dummy-host" @@ -162,13 +101,13 @@ function createHost(checkType, checkConfig, num, checkEnabled) { } } -loop(10, lambda num: { +__for (num in range(10)) { createHost("ok", "ok", num, true) - createHost("random", "random,flap", num, true) + createHost("random", "random,flapping", num, true) createHost("down", "warning,critical", num, true) createHost("unreachable", "unknown", num, true) createHost("pending", "pending", num, false) - createHost("flap", "flap", num, true) - }) + createHost("flap", "flapping", num, true) +} -// EOF \ No newline at end of file +// EOF From be6844c4588fa36ffb44a5a11e898210e946e81c Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 15 May 2014 13:44:21 +0200 Subject: [PATCH 23/55] Fix problems with the Puppet manifest when PostgreSQL's default encoding isn't UTF-8 fixes #6211 --- .vagrant-puppet/manifests/default.pp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.vagrant-puppet/manifests/default.pp b/.vagrant-puppet/manifests/default.pp index 0119837f4..265282885 100644 --- a/.vagrant-puppet/manifests/default.pp +++ b/.vagrant-puppet/manifests/default.pp @@ -27,7 +27,7 @@ exec { 'create-mysql-icinga2-db': exec{ 'create-pgsql-icinga-db': unless => 'sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname=\'icinga\'" | grep -q 1', command => 'sudo -u postgres psql -c "CREATE ROLE icinga WITH LOGIN PASSWORD \'icingaweb\';" && \ - sudo -u postgres createdb -O icinga -E UTF8 icinga && \ + sudo -u postgres createdb -O icinga -E UTF8 -T template0 icinga && \ sudo -u postgres createlang plpgsql icinga', require => Service['postgresql'] } @@ -485,7 +485,7 @@ exec { 'create-mysql-icinga_unittest-db': exec{ 'create-pgsql-icinga_unittest-db': unless => 'sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname=\'icinga_unittest\'" | grep -q 1', command => 'sudo -u postgres psql -c "CREATE ROLE icinga_unittest WITH LOGIN PASSWORD \'icinga_unittest\';" && \ - sudo -u postgres createdb -O icinga_unittest -E UTF8 icinga_unittest && \ + sudo -u postgres createdb -O icinga_unittest -E UTF8 -T template0 icinga_unittest && \ sudo -u postgres createlang plpgsql icinga_unittest', require => Service['postgresql'] } @@ -580,7 +580,7 @@ exec { 'create-mysql-icingaweb-db': exec { 'create-pgsql-icingaweb-db': unless => 'sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname=\'icingaweb\'" | grep -q 1', command => 'sudo -u postgres psql -c "CREATE ROLE icingaweb WITH LOGIN PASSWORD \'icinga\';" && \ - sudo -u postgres createdb -O icingaweb -E UTF8 icingaweb && \ + sudo -u postgres createdb -O icingaweb -E UTF8 -T template0 icingaweb && \ sudo -u postgres createlang plpgsql icingaweb', require => Service['postgresql'] } From 4a5fa5f17bad0dc526270390eee5b255ec7a3272 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Fri, 16 May 2014 13:33:30 +0200 Subject: [PATCH 24/55] Update Icinga 2 version in the Puppet manifest fixes #6219 --- .vagrant-puppet/manifests/default.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vagrant-puppet/manifests/default.pp b/.vagrant-puppet/manifests/default.pp index 265282885..db17e8576 100644 --- a/.vagrant-puppet/manifests/default.pp +++ b/.vagrant-puppet/manifests/default.pp @@ -6,7 +6,7 @@ include openldap Exec { path => '/bin:/usr/bin:/sbin' } $icingaVersion = '1.11.2' -$icinga2Version = '0.0.10' +$icinga2Version = '0.0.11' exec { 'create-mysql-icinga-db': unless => 'mysql -uicinga -picinga icinga', From ef56f2163eddedeafe13f346c54f00cb5bfbf2df Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 20 May 2014 11:11:32 +0200 Subject: [PATCH 25/55] Documentation: Fix missing preferences*,sql fixes #6243 --- doc/installation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/installation.md b/doc/installation.md index c8ee79cb6..9de3f7d5c 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -75,6 +75,7 @@ create all database tables. You will find the installation guides for the differ > RPM packages install the schema into /usr/share/doc/icingaweb-<version>/schema bash$ mysql -u root -p icingaweb < etc/schema/accounts.mysql.sql + bash$ mysql -u root -p icingaweb < etc/schema/preferences.mysql.sql #### PostgreSQL @@ -108,6 +109,7 @@ And restart your database ('service postgresql restart' or '/etc/init.d/postgres > RPM packages install the schema into /usr/share/doc/icingaweb-<version>/schema bash$ psql -U icingaweb -a -f etc/schema/accounts.pgsql.sql + bash$ psql -U icingaweb -a -f etc/schema/preferences.pgsql.sql From b447225512d5aad1aaeeddc72fc63989b3c2ac6f Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 13:10:18 +0000 Subject: [PATCH 26/55] Web\Form: Revert "Fix subForm functionality" This reverts commit 51bac035ac1bdee2c63f680ec66120beb1081af3. The div element introduced by this commit breaks inline form layout --- library/Icinga/Web/Form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 5d5c3da85..02c9787f4 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -599,7 +599,7 @@ class Form extends Zend_Form $decorators = $this->getDecorators(); if (empty($decorators)) { $this->addDecorator('FormElements') - ->addDecorator('HtmlTag', array('tag' => 'div')) // Quickfix to get subForms to work + //->addDecorator('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form')) ->addDecorator('Form'); } From e6d80ae1f6578ac35d6506996ac0b56233203abb Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 13:27:58 +0000 Subject: [PATCH 27/55] IDO Queries: performance quickfixes Will be obsoleted by the new filter implementation, but for now it helps a little bit --- library/Icinga/Data/Db/TreeToSqlParser.php | 13 +++++++++++-- .../Backend/Ido/Query/ContactgroupQuery.php | 6 +++--- .../Backend/Ido/Query/CustomvarQuery.php | 14 +++++++++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/library/Icinga/Data/Db/TreeToSqlParser.php b/library/Icinga/Data/Db/TreeToSqlParser.php index 92b42c356..67d1f944c 100644 --- a/library/Icinga/Data/Db/TreeToSqlParser.php +++ b/library/Icinga/Data/Db/TreeToSqlParser.php @@ -75,7 +75,12 @@ class TreeToSqlParser if (count($right) > 1) { return 'IN'; } else { - return 'LIKE'; + foreach ($right as $r) { + if (strpos($r, '*') !== false) { + return 'LIKE'; + } + } + return '='; } case Node::OPERATOR_EQUALS_NOT: if (count($right) > 1) { @@ -171,7 +176,11 @@ class TreeToSqlParser if ($node->context === Node::CONTEXT_TIMESTRING && !is_numeric($value)) { $value = strtotime($value); } - $values[] = $this->query->getDatasource()->getConnection()->quote($value); + if (preg_match('/^\d+$/', $value)) { + $values[] = $value; + } else { + $values[] = $this->query->getDatasource()->getConnection()->quote($value); + } } $valueString = join(',', $values); diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php index c5b7e0e26..9cbea76e6 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php @@ -113,9 +113,9 @@ class ContactgroupQuery extends IdoQuery +-------------------------+-------------+------------+------------------------+ */ - $this->baseQuery->join( - // array('scg' => $this->prefix . 'service_contactgroups'), - array('scg' => $scgSub), + $this->baseQuery->distinct()->join( + array('scg' => $this->prefix . 'service_contactgroups'), + // array('scg' => $scgSub), 'scg.contactgroup_object_id = cg.contactgroup_object_id', array() )->join( diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php index d4e516dc2..6f0810a4a 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php @@ -14,11 +14,23 @@ class CustomvarQuery extends IdoQuery 'service_host_name' => 'cvo.name1 COLLATE latin1_general_ci', 'service_description' => 'cvo.name2 COLLATE latin1_general_ci', 'contact_name' => 'cvo.name1 COLLATE latin1_general_ci', - 'object_type' => "CASE cvo.objecttype_id WHEN 1 THEN 'host' WHEN 2 THEN 'service' WHEN 10 THEN 'contact' ELSE 'invalid' END" + 'object_type' => "CASE cvo.objecttype_id WHEN 1 THEN 'host' WHEN 2 THEN 'service' WHEN 10 THEN 'contact' ELSE 'invalid' END", + 'object_type_id' => 'cvo.objecttype_id' // 'object_type' => "CASE cvo.objecttype_id WHEN 1 THEN 'host' WHEN 2 THEN 'service' WHEN 3 THEN 'hostgroup' WHEN 4 THEN 'servicegroup' WHEN 5 THEN 'hostescalation' WHEN 6 THEN 'serviceescalation' WHEN 7 THEN 'hostdependency' WHEN 8 THEN 'servicedependency' WHEN 9 THEN 'timeperiod' WHEN 10 THEN 'contact' WHEN 11 THEN 'contactgroup' WHEN 12 THEN 'command' ELSE 'other' END" ), ); + public function where($expression, $parameters = null) + { + $types = array('host' => 1, 'service' => 2, 'contact' => 10); + if ($expression === 'object_type') { + parent::where('object_type_id', $types[$parameters]); + } else { + parent::where($expression, $parameters); + } + return $this; + } + protected function joinBaseTables() { $this->baseQuery = $this->db->select()->from( From 33e326a2321d608157803f7ff5599f80e566ea9b Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 13:31:13 +0000 Subject: [PATCH 28/55] list/services: ignore broken service image hacks People used to configure something like "dot.png'> - service_icon_image): ?> + service_icon_image && ! preg_match('/[\'"]/', $service->service_icon_image)): ?> icon($this->resolveMacros($service->service_icon_image, $service)) ?> service_display_name ?>showHost): ?> on host_name; ?> From 358b2582bc6827c38b67b77c73e65b025e07531a Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 13:40:52 +0000 Subject: [PATCH 29/55] ErrorController: show valid title for exceptions Multiline strings are not considered being a valid title. This patch strips all but the first line from the exception message when setting the title attribute. --- application/controllers/ErrorController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/application/controllers/ErrorController.php b/application/controllers/ErrorController.php index 343a40b7f..74e2e8b52 100644 --- a/application/controllers/ErrorController.php +++ b/application/controllers/ErrorController.php @@ -66,8 +66,9 @@ class ErrorController extends ActionController break; default: + $title = preg_replace('/\r?\n.*$/s', '', $exception->getMessage()); $this->getResponse()->setHttpResponseCode(500); - $this->view->title = 'Server error: ' . $exception->getMessage(); + $this->view->title = 'Server error: ' . $title; $this->view->message = $exception->getMessage(); if ($this->getInvokeArg('displayExceptions') == true) { $this->view->stackTrace = $exception->getTraceAsString(); From 4e88a4e0080b364b710d587967e094ca9d9e5322 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 13:49:35 +0000 Subject: [PATCH 30/55] Web\Url: add a shift() method This methods allows to retrieve an URL param while removing it from the URL object --- library/Icinga/Web/Url.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/library/Icinga/Web/Url.php b/library/Icinga/Web/Url.php index 8476e40ce..e00fad03c 100644 --- a/library/Icinga/Web/Url.php +++ b/library/Icinga/Web/Url.php @@ -463,6 +463,25 @@ class Url return $this; } + /** + * Shift a query parameter from this URL if it exists, otherwise $default + * + * @param string $param Parameter name + * @param mixed $default Default value in case $param does not exist + * + * @return mixed + */ + public function shift($param, $default = null) + { + if (isset($this->params[$param])) { + $ret = $this->params[$param]; + unset($this->params[$param]); + } else { + $ret = $default; + } + return $ret; + } + /** * Return a copy of this url without the parameter given * From 8f77ce607e3d94cac3c4fbc0df3a96a82957e5a2 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 13:53:36 +0000 Subject: [PATCH 31/55] show/services: don't navigate to the right When using list/services for show/services (services for a single host) we us an ugly PREG-based hack fixing the base link target. This got broken by the multiselect feature, now it's working again. We need a better solution for this. --- .../application/views/scripts/list/services.phtml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/modules/monitoring/application/views/scripts/list/services.phtml b/modules/monitoring/application/views/scripts/list/services.phtml index 28371c931..346555a07 100644 --- a/modules/monitoring/application/views/scripts/list/services.phtml +++ b/modules/monitoring/application/views/scripts/list/services.phtml @@ -9,20 +9,16 @@ if (!$this->compact): ?> Sort by sortControl ?> -paginationControl($services, null, null, array('preserve' => $this->preserve));?> - - -selectionToolbar('multi', $this->href('monitoring/multi/service', $query)); ?> +paginationControl($services, null, null, array('preserve' => $this->preserve)) ?> +selectionToolbar('multi', $this->href('monitoring/multi/service', $query)) ?>
-" - data-icinga-multiselect-data="service,host" -> + data-icinga-multiselect-data="service,host"> Date: Tue, 20 May 2014 13:57:28 +0000 Subject: [PATCH 32/55] ShowController: don't show a random service When you chose a host and clicked on "Services" the GUI used to show a random (the first) service. Made no sense, should work as expected right now. --- modules/monitoring/application/controllers/ShowController.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/monitoring/application/controllers/ShowController.php b/modules/monitoring/application/controllers/ShowController.php index b695389a4..e8f3dd1b4 100644 --- a/modules/monitoring/application/controllers/ShowController.php +++ b/modules/monitoring/application/controllers/ShowController.php @@ -58,8 +58,7 @@ class Monitoring_ShowController extends Controller { if ($this->getRequest()->getActionName() === 'host') { $this->view->object = new Host($this->getRequest()); - } elseif ($this->getRequest()->getActionName() === 'service' - || $this->getRequest()->getActionName() === 'services' ) { + } elseif ($this->getRequest()->getActionName() === 'service') { $this->view->object = new Service($this->getRequest()); } else { // TODO: Well... this could be done better From 800fe6c18d2ace30e7bfa80e94c32fdae467cea5 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 14:01:14 +0000 Subject: [PATCH 33/55] css/tabs: waste less space for dropdown Dropdown arrow is smaller right now and is slightly rounded like the other tabs are. --- public/css/icinga/tabs.less | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/public/css/icinga/tabs.less b/public/css/icinga/tabs.less index 7150b7ec5..50cb64487 100644 --- a/public/css/icinga/tabs.less +++ b/public/css/icinga/tabs.less @@ -46,7 +46,11 @@ ul.tabs > li.active > a:focus { color: #555; } -ul.tabs li.active a, ul.tabs li.dropdown:hover, ul.tabs li.dropdown.hover { +ul.tabs li.dropdown > a{ + padding: 0 0.4em; +} + +ul.tabs li.active a, ul.tabs li.dropdown:hover a, ul.tabs li.dropdown.hover a { background-color: white; color: #333; } @@ -74,13 +78,16 @@ ul.dropdown-menu { /* Dropdown tabs after the fourth title should be right-aligned */ ul.tabs li:nth-child(n+5) ul.dropdown-menu { width: 13em; - margin-left: -9em; + margin-left: -11em; } ul.dropdown-menu { + box-shadow: 0.2em 0.2em 0.3em -0.2em #555; -moz-box-shadow: 0.2em 0.2em 0.3em -0.2em #555; -webkit-box-shadow: 0.2em 0.2em 0.3em -0.2em #555; - box-shadow: 0.2em 0.2em 0.3em -0.2em #555; + border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + -webkit-border-radius: 0 0 3px 3px; } ul.dropdown-menu li { From 79d3f18b6648f9476e1b12001dd777a07f578169 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 14:03:33 +0000 Subject: [PATCH 34/55] js/ui: remove hardcoded/duplicated with/height --- public/js/icinga/ui.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/js/icinga/ui.js b/public/js/icinga/ui.js index bdb9dc714..e6e57db7c 100644 --- a/public/js/icinga/ui.js +++ b/public/js/icinga/ui.js @@ -664,8 +664,8 @@ '' ); }, From 67144407e61e765aff7e036eafc56f6b1fea51b2 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 14:05:30 +0000 Subject: [PATCH 35/55] js/events: do temporarily not respect tab focus This has been added for keyboard navigation but caused some trouble. Postponed for now. --- public/js/icinga/events.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/js/icinga/events.js b/public/js/icinga/events.js index 39cd3cd00..48b39be13 100644 --- a/public/js/icinga/events.js +++ b/public/js/icinga/events.js @@ -190,7 +190,8 @@ dropdownLeave: function () { var $li = $(this); setTimeout(function () { - if (! $li.is('li:hover') && ! $li.find(':focus')) { + // TODO: make this behave well together with keyboard navigation + if (! $li.is('li:hover') /*&& ! $li.find('a:focus')*/) { $li.removeClass('hover'); } }, 300); From de0b97b4cad5c5b4154839d88e4f355810b2f99b Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 14:07:19 +0000 Subject: [PATCH 36/55] js/events: improve search field change detection This used to be nasty since "search" is the field with the initial focus. Right now we detect "real" changes, this might be implemented in a more generic way for all autocompleting fields later on. --- public/js/icinga/events.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/public/js/icinga/events.js b/public/js/icinga/events.js index 48b39be13..18f57561d 100644 --- a/public/js/icinga/events.js +++ b/public/js/icinga/events.js @@ -9,6 +9,8 @@ Icinga.Events = function (icinga) { this.icinga = icinga; + + this.searchValue = ''; }; Icinga.Events.prototype = { @@ -27,6 +29,11 @@ this.applyHandlers($('#layout')); this.icinga.ui.prepareContainers(); this.icinga.ui.prepareMultiselectTables($(document)); + + // Remember initial search field value if any + if ($('#menu input.search').val().length) { + this.searchValue = $('#menu input.search').val(); + } }, // TODO: What's this? @@ -108,7 +115,7 @@ // We support an 'autosubmit' class on dropdown form elements $(document).on('change', 'form select.autosubmit', { self: this }, this.autoSubmitForm); - $(document).on('keyup', '#menu input.search', {self: this}, this.autoSubmitForm); + $(document).on('keyup', '#menu input.search', {self: this}, this.autoSubmitSearch); $(document).on('mouseenter', '.historycolorgrid td', this.historycolorgridHover); $(document).on('mouseleave', '.historycolorgrid td', this.historycolorgidUnhover); @@ -233,6 +240,15 @@ $(this).removeClass('hover'); }, + autoSubmitSearch: function(event) { + var self = event.data.self; + if ($('#menu input.search').val() === self.searchValue) { + return; + } + self.searchValue = $('#menu input.search').val(); + return self.autoSubmitForm(event); + }, + autoSubmitForm: function (event) { return event.data.self.submitForm(event, true); }, From ad91c420a00294e53f454e04324688a4f224e69e Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 14:58:58 +0000 Subject: [PATCH 37/55] js/loader + css: highlight containers loading slow I missused the "impact" CSS class for this as it perfectly fit's this use case. A container loading slow IS an impact. Added CSS transitions, this way it feels better on modern browsers. The longer it takes to load a page the darker will get it's background. --- public/css/icinga/layout-colors.less | 12 ++++++++---- public/css/icinga/tabs.less | 8 ++++++-- public/js/icinga/loader.js | 3 +++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/public/css/icinga/layout-colors.less b/public/css/icinga/layout-colors.less index 36225c66b..a1e7fe241 100644 --- a/public/css/icinga/layout-colors.less +++ b/public/css/icinga/layout-colors.less @@ -26,14 +26,18 @@ background-color: white; } -.container { - background-color: white; -} - #col1.impact, #col2.impact, #col3.impact { background-color: #ddd; + transition: background-color 0.5s linear; + -moz-transition: background-color 1.5s linear; + -o-transition: background-color 1.5s linear; + -webkit-transition: background-color 1.5s linear; .controls { background-color: #ddd; + transition: background-color 0.5s linear; + -moz-transition: background-color 1.5s linear; + -o-transition: background-color 1.5s linear; + -webkit-transition: background-color 1.5s linear; } } diff --git a/public/css/icinga/tabs.less b/public/css/icinga/tabs.less index 50cb64487..ace37bece 100644 --- a/public/css/icinga/tabs.less +++ b/public/css/icinga/tabs.less @@ -55,8 +55,12 @@ ul.tabs li.active a, ul.tabs li.dropdown:hover a, ul.tabs li.dropdown.hover a { color: #333; } -.impact ul.tabs li.active a, .impact ul.tabs li.dropdown:hover { - background: white; +.impact ul.tabs li.active a, .impact ul.tabs li.dropdown:hover, .impact ul.tabs li.dropdown.hover a { + background-color: #ddd; + transition: background-color 0.5s linear; + -moz-transition: background-color 1.5s linear; + -o-transition: background-color 1.5s linear; + -webkit-transition: background-color 1.5s linear; } ul.tabs li a:hover { diff --git a/public/js/icinga/loader.js b/public/js/icinga/loader.js index 2f9454223..32a7875d5 100644 --- a/public/js/icinga/loader.js +++ b/public/js/icinga/loader.js @@ -118,6 +118,9 @@ if (id) { this.requests[id] = req; } + if (! autorefresh) { + req.$target.addClass('impact'); + } this.icinga.ui.refreshDebug(); return req; }, From 4a2074f25079ca0de589646e1724f650285bf986 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 15:19:00 +0000 Subject: [PATCH 38/55] css/impact-transition: add initial delay, slower --- public/css/icinga/layout-colors.less | 16 ++++++++-------- public/css/icinga/tabs.less | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/public/css/icinga/layout-colors.less b/public/css/icinga/layout-colors.less index a1e7fe241..0c54e4a12 100644 --- a/public/css/icinga/layout-colors.less +++ b/public/css/icinga/layout-colors.less @@ -28,16 +28,16 @@ #col1.impact, #col2.impact, #col3.impact { background-color: #ddd; - transition: background-color 0.5s linear; - -moz-transition: background-color 1.5s linear; - -o-transition: background-color 1.5s linear; - -webkit-transition: background-color 1.5s linear; + transition: background-color 2s 1s linear; + -moz-transition: background-color 2s 1s linear; + -o-transition: background-color 2s 1s linear; + -webkit-transition: background-color 2s 1s linear; .controls { background-color: #ddd; - transition: background-color 0.5s linear; - -moz-transition: background-color 1.5s linear; - -o-transition: background-color 1.5s linear; - -webkit-transition: background-color 1.5s linear; + transition: background-color 2s 1s linear; + -moz-transition: background-color 2s 1s linear; + -o-transition: background-color 2s 1s linear; + -webkit-transition: background-color 2s 1s linear; } } diff --git a/public/css/icinga/tabs.less b/public/css/icinga/tabs.less index ace37bece..2999a1928 100644 --- a/public/css/icinga/tabs.less +++ b/public/css/icinga/tabs.less @@ -57,10 +57,10 @@ ul.tabs li.active a, ul.tabs li.dropdown:hover a, ul.tabs li.dropdown.hover a { .impact ul.tabs li.active a, .impact ul.tabs li.dropdown:hover, .impact ul.tabs li.dropdown.hover a { background-color: #ddd; - transition: background-color 0.5s linear; - -moz-transition: background-color 1.5s linear; - -o-transition: background-color 1.5s linear; - -webkit-transition: background-color 1.5s linear; + transition: background-color 2s 1s linear; + -moz-transition: background-color 2s 1s linear; + -o-transition: background-color 2s 1s linear; + -webkit-transition: background-color 2s 1s linear; } ul.tabs li a:hover { From 9fbdb65a4b3eb8f518617696c167e534800a6cb4 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 20 May 2014 20:07:09 +0200 Subject: [PATCH 39/55] Add check source to host/service details refs #5814 --- .../application/views/helpers/CheckSource.php | 14 ++++++++++++++ .../scripts/show/components/checksource.phtml | 7 +++++++ .../application/views/scripts/show/host.phtml | 1 + .../application/views/scripts/show/service.phtml | 1 + .../Monitoring/Backend/Ido/Query/StatusQuery.php | 2 ++ .../Backend/Statusdat/Query/StatusQuery.php | 2 ++ .../library/Monitoring/DataView/HostStatus.php | 1 + .../library/Monitoring/DataView/ServiceStatus.php | 2 ++ 8 files changed, 30 insertions(+) create mode 100644 modules/monitoring/application/views/helpers/CheckSource.php create mode 100644 modules/monitoring/application/views/scripts/show/components/checksource.phtml diff --git a/modules/monitoring/application/views/helpers/CheckSource.php b/modules/monitoring/application/views/helpers/CheckSource.php new file mode 100644 index 000000000..55efcde56 --- /dev/null +++ b/modules/monitoring/application/views/helpers/CheckSource.php @@ -0,0 +1,14 @@ +view->escape($source); + } +} diff --git a/modules/monitoring/application/views/scripts/show/components/checksource.phtml b/modules/monitoring/application/views/scripts/show/components/checksource.phtml new file mode 100644 index 000000000..a0ea90ca5 --- /dev/null +++ b/modules/monitoring/application/views/scripts/show/components/checksource.phtml @@ -0,0 +1,7 @@ +check_source) return ?> + + + + diff --git a/modules/monitoring/application/views/scripts/show/host.phtml b/modules/monitoring/application/views/scripts/show/host.phtml index d21fed261..189729192 100644 --- a/modules/monitoring/application/views/scripts/show/host.phtml +++ b/modules/monitoring/application/views/scripts/show/host.phtml @@ -13,6 +13,7 @@ render('show/components/downtime.phtml') ?> render('show/components/flapping.phtml') ?> render('show/components/perfdata.phtml') ?> +render('show/components/checksource.phtml') ?> render('show/components/actions.phtml') ?> render('show/components/command.phtml') ?> render('show/components/hostgroups.phtml') ?> diff --git a/modules/monitoring/application/views/scripts/show/service.phtml b/modules/monitoring/application/views/scripts/show/service.phtml index 18ef09cd6..1c8f42c9f 100644 --- a/modules/monitoring/application/views/scripts/show/service.phtml +++ b/modules/monitoring/application/views/scripts/show/service.phtml @@ -13,6 +13,7 @@ render('show/components/downtime.phtml') ?> render('show/components/flapping.phtml') ?> render('show/components/perfdata.phtml') ?> +render('show/components/checksource.phtml') ?> render('show/components/actions.phtml') ?> render('show/components/command.phtml') ?> render('show/components/servicegroups.phtml') ?> diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php index eb5702dbb..fd582e096 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php @@ -52,6 +52,7 @@ class StatusQuery extends IdoQuery 'host_output' => 'hs.output', 'host_long_output' => 'hs.long_output', 'host_perfdata' => 'hs.perfdata', + 'host_check_source' => 'hs.check_source', 'host_acknowledged' => 'hs.problem_has_been_acknowledged', 'host_in_downtime' => 'CASE WHEN (hs.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END', 'host_handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END', @@ -181,6 +182,7 @@ class StatusQuery extends IdoQuery 'service_output' => 'ss.output', 'service_long_output' => 'ss.long_output', 'service_perfdata' => 'ss.perfdata', + 'service_check_source' => 'ss.check_source', 'service_acknowledged' => 'ss.problem_has_been_acknowledged', 'service_in_downtime' => 'CASE WHEN (ss.scheduled_downtime_depth = 0 OR ss.scheduled_downtime_depth IS NULL) THEN 0 ELSE 1 END', 'service_handled' => 'CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END', diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php index 1fa082254..d17468bd3 100644 --- a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php @@ -30,6 +30,7 @@ class StatusQuery extends StatusdatQuery 'host_output' => 'host.status.plugin_output', 'host_long_output' => 'host.status.long_plugin_output', 'host_perfdata' => 'host.status.performance_data', + 'host_check_source' => 'host.status.check_source', 'host_acknowledged' => 'host.status.problem_has_been_acknowledged', 'host_last_state_change' => 'host.status.last_state_change', 'host_last_hard_state' => 'host.status.last_hard_state', @@ -82,6 +83,7 @@ class StatusQuery extends StatusdatQuery 'service_output' => 'service.status.output', 'service_long_output' => 'service.status.long_output', 'service_perfdata' => 'service.status.perfdata', + 'service_check_source' => 'service.status.check_source', 'service_acknowledged' => 'service.status.problem_has_been_acknowledged', 'service_last_state_change' => 'service.status.last_state_change', 'service_check_command' => 'service.status.check_command', diff --git a/modules/monitoring/library/Monitoring/DataView/HostStatus.php b/modules/monitoring/library/Monitoring/DataView/HostStatus.php index c0a4e40cf..cf65df80a 100644 --- a/modules/monitoring/library/Monitoring/DataView/HostStatus.php +++ b/modules/monitoring/library/Monitoring/DataView/HostStatus.php @@ -62,6 +62,7 @@ class HostStatus extends DataView 'host_long_output', 'host_check_command', 'host_perfdata', + 'host_check_source', 'host_passive_checks_enabled', 'host_passive_checks_enabled_changed', 'host_obsessing', diff --git a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php index c7823ee87..5e34fb5aa 100644 --- a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php +++ b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php @@ -90,6 +90,7 @@ class ServiceStatus extends DataView 'host_ipv4', 'host_severity', 'host_perfdata', + 'host_check_source', 'host_active_checks_enabled', 'host_passive_checks_enabled', 'host_last_hard_state', @@ -102,6 +103,7 @@ class ServiceStatus extends DataView 'service_hard_state', 'service_problem', 'service_perfdata', + 'service_check_source', 'service_active_checks_enabled', 'service_active_checks_enabled_changed', 'service_passive_checks_enabled', From 31fa794440fcd349cdbca148730c268292e5bd4b Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 20:36:39 +0000 Subject: [PATCH 40/55] monitoring/ido: implement IDO version support We want to make use of new IDO features without breaking compatibility. This is a quickfix as otherwise we would currently break everything below 1.10. Code contains a few TODOs as this needs improvement. --- .../Monitoring/Backend/Ido/Query/IdoQuery.php | 39 +++++++++++++++++++ .../Backend/Ido/Query/StatusQuery.php | 4 ++ .../Monitoring/DataView/ServiceStatus.php | 2 +- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php index e682c33bf..471856775 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php @@ -35,6 +35,8 @@ use Icinga\Application\Benchmark; use Icinga\Exception\ProgrammingError; use Icinga\Filter\Query\Tree; use Icinga\Module\Monitoring\Filter\UrlViewFilter; +use Icinga\Application\Icinga; +use Icinga\Web\Session; /** * Base class for Ido Queries @@ -184,6 +186,18 @@ abstract class IdoQuery extends Query */ protected $allowCustomVars = false; + /** + * Current IDO version. This is bullshit and needs to be moved somewhere + * else. As someone decided that we need no Backend-specific connection + * class unfortunately there is no better place right now. And as of the + * 'check_source' patch we need a quick fix immediately. So here you go. + * + * TODO: Fix this. + * + * @var string + */ + protected static $idoVersion; + /** * Return true when the column is an aggregate column * @@ -580,4 +594,29 @@ abstract class IdoQuery extends Query $query = new $class($this->ds, $columns); return $query; } + + // TODO: Move this away, see note related to $idoVersion var + protected function getIdoVersion() + { + if (self::$idoVersion === null) { + $session = null; + if (Icinga::app()->isWeb()) { + // TODO: Once we have version per connection we should choose a + // namespace based on resource name + $session = Session::getSession()->getNamespace('monitoring/ido'); + if (isset($session->version)) { + self::$idoVersion = $session->version; + return self::$idoVersion; + } + } + self::$idoVersion = $this->db->fetchOne( + $this->db->select()->from($this->prefix . 'dbversion', 'version') + ); + if ($session !== null) { + $session->version = self::$idoVersion; + $session->write(); // <- WHY? I don't want to care about this! + } + } + return self::$idoVersion; + } } diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php index fd582e096..d1c6a251a 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php @@ -305,6 +305,10 @@ class StatusQuery extends IdoQuery protected function joinBaseTables() { + if (version_compare($this->getIdoVersion(), '1.10.0', '<')) { + $this->columnMap['hoststatus']['host_check_source'] = '(NULL)'; + $this->columnMap['servicestatus']['service_check_source'] = '(NULL)'; + } $this->baseQuery = $this->db->select()->from( array('ho' => $this->prefix . 'objects'), array() diff --git a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php index 5e34fb5aa..839c7da55 100644 --- a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php +++ b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php @@ -103,7 +103,7 @@ class ServiceStatus extends DataView 'service_hard_state', 'service_problem', 'service_perfdata', - 'service_check_source', + 'service_check_source', 'service_active_checks_enabled', 'service_active_checks_enabled_changed', 'service_passive_checks_enabled', From 941ff2a98096f73cacbe49bf732a5808b360c5e0 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 20:39:02 +0000 Subject: [PATCH 41/55] monitoring/show: remove CheckSource helper It isn't doing anything but escape, so we can safely skip it. --- .../application/views/helpers/CheckSource.php | 14 -------------- .../scripts/show/components/checksource.phtml | 4 ++-- 2 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 modules/monitoring/application/views/helpers/CheckSource.php diff --git a/modules/monitoring/application/views/helpers/CheckSource.php b/modules/monitoring/application/views/helpers/CheckSource.php deleted file mode 100644 index 55efcde56..000000000 --- a/modules/monitoring/application/views/helpers/CheckSource.php +++ /dev/null @@ -1,14 +0,0 @@ -view->escape($source); - } -} diff --git a/modules/monitoring/application/views/scripts/show/components/checksource.phtml b/modules/monitoring/application/views/scripts/show/components/checksource.phtml index a0ea90ca5..921654eeb 100644 --- a/modules/monitoring/application/views/scripts/show/components/checksource.phtml +++ b/modules/monitoring/application/views/scripts/show/components/checksource.phtml @@ -1,7 +1,7 @@ -check_source) return ?> +check_source) || ! $object->check_source) return ?> From ef2ac077c8ba87ccf69794001b80ee6ba0bca69b Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 20 May 2014 23:45:48 +0200 Subject: [PATCH 42/55] Fix typo in flapping note --- .../application/views/scripts/show/components/flapping.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/monitoring/application/views/scripts/show/components/flapping.phtml b/modules/monitoring/application/views/scripts/show/components/flapping.phtml index b6dbe0cee..0cf9d6408 100644 --- a/modules/monitoring/application/views/scripts/show/components/flapping.phtml +++ b/modules/monitoring/application/views/scripts/show/components/flapping.phtml @@ -6,7 +6,7 @@ if ($object->is_flapping) { 'Flapping', $this->icon('flapping.png', 'Flapping'), sprintf( - 'Currently flapping witgh a %.2f%% state change rate', + 'Currently flapping with a %.2f%% state change rate', $object->percent_state_change ) ); From d155c7a3fcbe173dc96e0169e5a2d78e758bdc9d Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 20 May 2014 23:46:33 +0200 Subject: [PATCH 43/55] Fix checks for empty check source attribute refs ##5814 --- .../application/views/scripts/show/components/checksource.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/monitoring/application/views/scripts/show/components/checksource.phtml b/modules/monitoring/application/views/scripts/show/components/checksource.phtml index 921654eeb..60bb944f3 100644 --- a/modules/monitoring/application/views/scripts/show/components/checksource.phtml +++ b/modules/monitoring/application/views/scripts/show/components/checksource.phtml @@ -1,4 +1,4 @@ -check_source) || ! $object->check_source) return ?> +check_source) return ?> +
translate('Check Source') ?> + checkSource($object->check_source) ?> +
translate('Check Source') ?> - checkSource($object->check_source) ?> + escape($object->check_source) ?>
translate('Check Source') ?> From 194914917a62d11ccf1416e2a941167249492262 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 21:55:32 +0000 Subject: [PATCH 44/55] js/events: initialize only existing search field Formlerly JS failed on layouts without menu, should be fixed now. --- public/js/icinga/events.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/public/js/icinga/events.js b/public/js/icinga/events.js index 18f57561d..cfaea02e1 100644 --- a/public/js/icinga/events.js +++ b/public/js/icinga/events.js @@ -29,11 +29,6 @@ this.applyHandlers($('#layout')); this.icinga.ui.prepareContainers(); this.icinga.ui.prepareMultiselectTables($(document)); - - // Remember initial search field value if any - if ($('#menu input.search').val().length) { - this.searchValue = $('#menu input.search').val(); - } }, // TODO: What's this? @@ -81,6 +76,12 @@ // replace all sparklines $('span.sparkline', el).sparkline('html', { enableTagOptions: true }); + + var searchField = $('#menu input.search', el); + // Remember initial search field value if any + if (searchField.length && searchField.val().length) { + this.searchValue = searchField.val(); + } }, /** From 76c1aa73c86a39cd60fcbc0b661fd9322d63f5cc Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 22:13:39 +0000 Subject: [PATCH 45/55] Monitoring\Controller: remove obsolete namespaces --- modules/monitoring/library/Monitoring/Controller.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/monitoring/library/Monitoring/Controller.php b/modules/monitoring/library/Monitoring/Controller.php index 3ae5e14a4..a5d17b89e 100644 --- a/modules/monitoring/library/Monitoring/Controller.php +++ b/modules/monitoring/library/Monitoring/Controller.php @@ -29,8 +29,6 @@ namespace Icinga\Module\Monitoring; -use Icinga\Application\Config as IcingaConfig; -use Icinga\Module\Monitoring\DataView\ServiceStatus as ServiceStatusView; use Icinga\Web\Controller\ActionController; use Icinga\File\Csv; From a7b8e0023d9905d18e494cb8305c0c98994b0e48 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 22:19:26 +0000 Subject: [PATCH 46/55] Monitoring\Object: explictely define columns Define the colums we use instead of fetching "everything" status view provides. Without this performance degrades with every new feature. --- .../Monitoring/Object/AbstractObject.php | 5 -- .../library/Monitoring/Object/Host.php | 43 +++++++++- .../library/Monitoring/Object/Service.php | 85 ++++++++++++++++++- 3 files changed, 126 insertions(+), 7 deletions(-) diff --git a/modules/monitoring/library/Monitoring/Object/AbstractObject.php b/modules/monitoring/library/Monitoring/Object/AbstractObject.php index 23417f034..c531580e1 100644 --- a/modules/monitoring/library/Monitoring/Object/AbstractObject.php +++ b/modules/monitoring/library/Monitoring/Object/AbstractObject.php @@ -251,11 +251,6 @@ abstract class AbstractObject return $this->$expandedName; } - public function getRequest() - { - return $this->request; - } - public static function fromRequest(Request $request) { if ($request->has('service') && $request->has('host')) { diff --git a/modules/monitoring/library/Monitoring/Object/Host.php b/modules/monitoring/library/Monitoring/Object/Host.php index 41a6dbb01..9540a238b 100644 --- a/modules/monitoring/library/Monitoring/Object/Host.php +++ b/modules/monitoring/library/Monitoring/Object/Host.php @@ -28,7 +28,48 @@ class Host extends AbstractObject protected function getProperties() { - $this->view = HostStatus::fromRequest($this->getRequest()); + $this->view = HostStatus::fromRequest($this->request, array( + 'host_name', + 'host_alias', + 'host_address', + 'host_state', + 'host_state_type', + 'host_handled', + 'host_in_downtime', + 'host_acknowledged', + 'host_last_state_change', + 'host_last_notification', + 'host_last_check', + 'host_next_check', + 'host_check_execution_time', + 'host_check_latency', + 'host_check_source', + 'host_output', + 'host_long_output', + 'host_check_command', + 'host_perfdata', + 'host_passive_checks_enabled', + 'host_passive_checks_enabled_changed', + 'host_obsessing', + 'host_obsessing_changed', + 'host_notifications_enabled', + 'host_notifications_enabled_changed', + 'host_event_handler_enabled', + 'host_event_handler_enabled_changed', + 'host_flap_detection_enabled', + 'host_flap_detection_enabled_changed', + 'host_active_checks_enabled', + 'host_active_checks_enabled_changed', + 'host_current_check_attempt', + 'host_max_check_attempts', + 'host_current_notification_number', + 'host_percent_state_change', + 'host_is_flapping', + 'host_action_url', + 'host_notes_url', + 'host_modified_host_attributes', + 'host_problem' + )); return $this->view->getQuery()->fetchRow(); } } diff --git a/modules/monitoring/library/Monitoring/Object/Service.php b/modules/monitoring/library/Monitoring/Object/Service.php index 2a661f7b7..76c7bac9b 100644 --- a/modules/monitoring/library/Monitoring/Object/Service.php +++ b/modules/monitoring/library/Monitoring/Object/Service.php @@ -29,7 +29,90 @@ class Service extends AbstractObject protected function getProperties() { - $this->view = ServiceStatus::fromRequest($this->getRequest()); + $this->view = ServiceStatus::fromRequest($this->request, array( + 'host_name', + 'host_state', + 'host_state_type', + 'host_last_state_change', + 'host_address', + 'host_problem', + 'host_handled', + 'service_description', + 'service_display_name', + 'service_state', + 'service_in_downtime', + 'service_acknowledged', + 'service_handled', + 'service_unhandled', + 'service_output', + 'service_last_state_change', + 'service_icon_image', + 'service_long_output', + 'service_is_flapping', + 'service_state_type', + 'service_severity', + 'service_last_check', + 'service_notifications_enabled', + 'service_notifications_enabled_changed', + 'service_action_url', + 'service_notes_url', + 'service_last_check', + 'service_next_check', + 'service_attempt', + 'service_last_notification', + 'service_check_command', + 'service_check_source', + 'service_current_notification_number', + 'host_icon_image', + 'host_acknowledged', + 'host_output', + 'host_long_output', + 'host_in_downtime', + 'host_is_flapping', + 'host_last_check', + 'host_notifications_enabled', + 'host_unhandled_service_count', + 'host_action_url', + 'host_notes_url', + 'host_last_comment', + 'host_display_name', + 'host_alias', + 'host_ipv4', + 'host_severity', + 'host_perfdata', + 'host_active_checks_enabled', + 'host_passive_checks_enabled', + 'host_last_hard_state', + 'host_last_hard_state_change', + 'host_last_time_up', + 'host_last_time_down', + 'host_last_time_unreachable', + 'host_modified_host_attributes', + 'host', + 'service', + 'service_hard_state', + 'service_problem', + 'service_perfdata', + 'service_active_checks_enabled', + 'service_active_checks_enabled_changed', + 'service_passive_checks_enabled', + 'service_passive_checks_enabled_changed', + 'service_last_hard_state', + 'service_last_hard_state_change', + 'service_last_time_ok', + 'service_last_time_warning', + 'service_last_time_critical', + 'service_last_time_unknown', + 'service_current_check_attempt', + 'service_max_check_attempts', + 'service_obsessing', + 'service_obsessing_changed', + 'service_event_handler_enabled', + 'service_event_handler_enabled_changed', + 'service_flap_detection_enabled', + 'service_flap_detection_enabled_changed', + 'service_modified_service_attributes', + )); return $this->view->getQuery()->fetchRow(); } } From 8b28bdc82a6a31308caa4c62f59c9564cc05bedb Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 22:22:48 +0000 Subject: [PATCH 47/55] Monitoring\Object: small fix for strange private's --- modules/monitoring/library/Monitoring/Object/AbstractObject.php | 1 + modules/monitoring/library/Monitoring/Object/Host.php | 1 - modules/monitoring/library/Monitoring/Object/Service.php | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/monitoring/library/Monitoring/Object/AbstractObject.php b/modules/monitoring/library/Monitoring/Object/AbstractObject.php index c531580e1..de01845a4 100644 --- a/modules/monitoring/library/Monitoring/Object/AbstractObject.php +++ b/modules/monitoring/library/Monitoring/Object/AbstractObject.php @@ -33,6 +33,7 @@ abstract class AbstractObject public $customvars = array(); public $events = array(); + protected $view; private $properties = array(); private $request = null; diff --git a/modules/monitoring/library/Monitoring/Object/Host.php b/modules/monitoring/library/Monitoring/Object/Host.php index 9540a238b..7c89bc838 100644 --- a/modules/monitoring/library/Monitoring/Object/Host.php +++ b/modules/monitoring/library/Monitoring/Object/Host.php @@ -9,7 +9,6 @@ class Host extends AbstractObject { public $type = 'host'; public $prefix = 'host_'; - private $view = null; protected function applyObjectFilter(Query $query) { diff --git a/modules/monitoring/library/Monitoring/Object/Service.php b/modules/monitoring/library/Monitoring/Object/Service.php index 76c7bac9b..ab7209a85 100644 --- a/modules/monitoring/library/Monitoring/Object/Service.php +++ b/modules/monitoring/library/Monitoring/Object/Service.php @@ -9,7 +9,6 @@ class Service extends AbstractObject { public $type = 'service'; public $prefix = 'service_'; - private $view = null; protected function applyObjectFilter(Query $query) { From 79f3b3247466188c18e5ebaaac72118b2f4983ae Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 22:26:21 +0000 Subject: [PATCH 48/55] monitoring/viewscripts: avoid errors in comments PHP code may cause errors even if sitting in HTML comments. Also fixed a HTML nesting error in list/servicematrix and reduced indentation. --- .../views/scripts/list/eventhistory.phtml | 2 - .../views/scripts/list/servicematrix.phtml | 90 +++++++++---------- 2 files changed, 45 insertions(+), 47 deletions(-) diff --git a/modules/monitoring/application/views/scripts/list/eventhistory.phtml b/modules/monitoring/application/views/scripts/list/eventhistory.phtml index 5fe526739..fb8e1b212 100644 --- a/modules/monitoring/application/views/scripts/list/eventhistory.phtml +++ b/modules/monitoring/application/views/scripts/list/eventhistory.phtml @@ -1,9 +1,7 @@
tabs->render($this); ?>
- Sort by sortControl->render($this); ?> -
paginationControl($history, null, null, array('preserve' => $this->preserve)); ?>
diff --git a/modules/monitoring/application/views/scripts/list/servicematrix.phtml b/modules/monitoring/application/views/scripts/list/servicematrix.phtml index 0aa0c324c..224dd46c5 100644 --- a/modules/monitoring/application/views/scripts/list/servicematrix.phtml +++ b/modules/monitoring/application/views/scripts/list/servicematrix.phtml @@ -2,7 +2,7 @@
tabs; ?>
- Sort by sortControl->render($this); ?> + Sort by sortControl ?>
partial( 'pivottablePagination.phtml', @@ -15,7 +15,7 @@
- +
pivot->toArray(); @@ -23,57 +23,57 @@ $hostFilter = implode(',', array_keys($pivotData)); ?> $serviceStates): ?> - - - - + + + - - - + + + + + - - + + - - - + - + - -
  -
+
  + -
- - - -
+ + - + + + - · + ·
+
From 51c3fed743992e31bcc6b4f3cddd641d45f24dfa Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 22:39:03 +0000 Subject: [PATCH 49/55] File\Pdf: remove obsolete code --- library/Icinga/File/Pdf.php | 159 +----------------------------------- 1 file changed, 1 insertion(+), 158 deletions(-) diff --git a/library/Icinga/File/Pdf.php b/library/Icinga/File/Pdf.php index 4f3f24c90..fd90a0299 100644 --- a/library/Icinga/File/Pdf.php +++ b/library/Icinga/File/Pdf.php @@ -1,5 +1,4 @@ render(); $layout->content = $controller->getResponse(); $html = $layout->render(); - $imgDir = Url::fromPath('img'); $html = preg_replace('~src="' . $imgDir . '/~', 'src="' . Icinga::app()->getBootstrapDirecory() . '/img/', $html); - //echo $html; exit; $this->load_html($html); - - /* - // TODO: We need to find a solution for page footers - $font = Font_Metrics::get_font("helvetica", "bold"); - $canvas = $this->get_canvas(); - $canvas->page_text(555, 750, "{PAGE_NUM}/{PAGE_COUNT}", $font, 10, array(0,0,0)); - $dompdf->page_script(' - // $pdf is the variable containing a reference to the canvas object provided by dompdf - $pdf->line(10,730,800,730,array(0,0,0),1); - '); - */ $this->render(); $this->stream( sprintf( @@ -93,127 +59,4 @@ class Pdf extends DOMPDF ) ); } - - /** - * @param $body - * @param $css - */ -/* public function renderPage($body, $css) - { - $html = - '' - . '' - . '' - . $body - . '' - . ''; - if ($this->paginateTable === true) { - $doc = new DOMDocument(); - @$doc->loadHTML($html); - $this->paginateHtmlTables($doc); - $html = $doc->saveHtml(); - } - $this->load_html($html); - $this->render(); - }*/ - - /** - * Split up tables into multiple elements that each contain $rowsPerPage of all original rows - * - * NOTE: This is a workaround to fix the buggy page-break on table-rows in dompdf. - * - * @param DOMDocument $doc The html document containing the tables. - * - * @return array All paginated tables from the document. - */ -/* private function paginateHtmlTables(DOMDocument $doc) - { - $xpath = new DOMXPath($doc); - $tables = $xpath->query('.//table'); - $paginated = array(); - $j = 0; - - foreach ($tables as $table) { - $containerType = null; - $rows = $xpath->query('.//tr', $table); - $rowCnt = $rows->length; - $tableCnt = (Integer)ceil($rowCnt / $this->rowsPerPage); - $paginated[$j] = array(); - if ($rowCnt <= $this->rowsPerPage) { - continue; - } - // remove all rows from the original parent - foreach ($rows as $row) { - if (!isset($containerType)) { - $containerType = $row->parentNode->nodeName; - } - $row->parentNode->removeChild($row); - } - - // clone table for each additional page and fetch the row containers - $containers = array(); - $pages = array(); - - if ($this->tableInitialPageBreak) { - $this->pageBreak($doc, $table); - } - for ($i = 0; $i < $tableCnt; $i++) { - // clone table - $currentPage = $table->cloneNode(true); - $pages[$i] = $currentPage; - $table->parentNode->insertBefore($currentPage, $table); - - // put it in current paginated table - $paginated[$j] = $currentPage; - - // insert page-break - if ($i < $tableCnt - 1) { - $this->pageBreak($doc, $table); - } - - // fetch row container - $container = $xpath->query('.//' . $containerType, $currentPage)->item(0); - $containers[$i] = $container; - } - - $i = 0; - foreach ($rows as $row) { - $p = (Integer)floor($i / $this->rowsPerPage); - $containers[$p]->appendChild($row); - $i++; - } - - // remove original table - $table->parentNode->removeChild($table); - $j++; - } - return $paginated; - } - - private function pageBreak($doc, $before) - { - $div = $doc->createElement('div'); - $div->setAttribute('style', 'page-break-before: always;'); - $before->parentNode->insertBefore($div, $before); - } -*/ - /** - * Prepare the given css for rendering with DOMPDF, by removing or hiding all incompatible - * styles - * - * @param $css The css-string - * - * @return string A css-string that is ready to use for DOMPDF - */ - -// public static function prepareCss($css) -// { -// $css = preg_replace('/\*:\s*before\s*,\s*/', '', $css); -// $css = preg_replace('/\*\s*:\s*after\s*\{[^\}]*\}/', '', $css); -// return $css; -// } - -} -// @codeCoverageIgnoreEnd +} \ No newline at end of file From 78bc2b4ec7eda703fa932e1441f9b4f646db092b Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 22:39:32 +0000 Subject: [PATCH 50/55] Modules\Manager: no warning for duplicate modules Formerly we logged a warning if a module was found in multiple module paths. This is pointless, because as soon as you got a default module installed by your distribution and "upgraded" it via your web frontend this "error" will be the default. Logging at debug level right now. --- library/Icinga/Application/Modules/Manager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Application/Modules/Manager.php b/library/Icinga/Application/Modules/Manager.php index 050c6c275..6fefd3930 100644 --- a/library/Icinga/Application/Modules/Manager.php +++ b/library/Icinga/Application/Modules/Manager.php @@ -532,7 +532,7 @@ class Manager if (! array_key_exists($file, $this->installedBaseDirs)) { $this->installedBaseDirs[$file] = $canonical . '/' . $file; } else { - Logger::warning( + Logger::debug( 'Module "%s" already exists in installation path "%s" and is ignored.', $canonical . '/' . $file, $this->installedBaseDirs[$file] From bfff645a088ff0ba66a6bc110e8200cfb1edb3ce Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 22:41:34 +0000 Subject: [PATCH 51/55] layout-script: disable chrome translate suggestion The way Chrome suggests translation is ugly and may result in a GUI "jumping up and down". One more vendor specific meta attribute :( --- application/layouts/scripts/layout.phtml | 1 + 1 file changed, 1 insertion(+) diff --git a/application/layouts/scripts/layout.phtml b/application/layouts/scripts/layout.phtml index ad54ad9fa..c527edbd5 100644 --- a/application/layouts/scripts/layout.phtml +++ b/application/layouts/scripts/layout.phtml @@ -24,6 +24,7 @@ $isIframe = isset($_GET['_render']) && $_GET['_render'] === 'iframe'; + <?= $this->title ? $this->escape($this->title) : 'Icinga Web' ?> From 5e69d1d9979e611074bee5faa7fc09d42b7ff5eb Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 22:46:36 +0000 Subject: [PATCH 52/55] layout/pdf: fix module css support Containers need the correct module classes to get their correct CSS also for PDFs --- application/layouts/scripts/pdf.phtml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/application/layouts/scripts/pdf.phtml b/application/layouts/scripts/pdf.phtml index 500aec268..c4a1b25f7 100644 --- a/application/layouts/scripts/pdf.phtml +++ b/application/layouts/scripts/pdf.phtml @@ -2,6 +2,15 @@ use Icinga\Web\StyleSheet; + +$moduleName = $this->layout()->moduleName; +if ($moduleName) { + $moduleClass = ' icinga-module module-' . $moduleName; +} else { + $moduleClass = ''; +} + + ?> @@ -32,7 +41,7 @@ if ( isset($pdf) ) -->

escape($this->title) ?>

-
+
render('inline.phtml') ?>
From 24f2ae607fa16ea4901bd8cfeb1ab063287a19e0 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 22:48:06 +0000 Subject: [PATCH 53/55] Pdf/Charts: add initial chart support to PDFs Problem: TCPDF had SVG support, dompdf hasn't. This patch adds a first rudimentary PNG conversion and a sample implementation making use of such. --- library/Icinga/Application/webrouter.php | 11 ++++++++++ library/Icinga/Chart/Inline/PieChart.php | 23 +++++++++++++++++++-- library/Icinga/File/Pdf.php | 1 + library/vendor/dompdf/dompdf_config.inc.php | 4 ++-- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/library/Icinga/Application/webrouter.php b/library/Icinga/Application/webrouter.php index 2cf7a3155..bee27ee1d 100644 --- a/library/Icinga/Application/webrouter.php +++ b/library/Icinga/Application/webrouter.php @@ -87,6 +87,17 @@ if (in_array($path, $special)) { $pie->initFromRequest(); echo $pie->render(); +} elseif ($path === 'png/chart.php') { + if (!array_key_exists('data', $_GET)) { + return false; + } + include __DIR__ . '/EmbeddedWeb.php'; + EmbeddedWeb::start(); + header('Content-Type: image/png'); + $pie = new PieChart(); + $pie->initFromRequest(); + $pie->toPng(); + } elseif (file_exists($baseDir . '/' . $path) && is_file($baseDir . '/' . $path)) { return false; } else { diff --git a/library/Icinga/Chart/Inline/PieChart.php b/library/Icinga/Chart/Inline/PieChart.php index 687e28f08..369ae6b9b 100644 --- a/library/Icinga/Chart/Inline/PieChart.php +++ b/library/Icinga/Chart/Inline/PieChart.php @@ -31,12 +31,14 @@ namespace Icinga\Chart\Inline; use Icinga\Chart\PieChart as PieChartRenderer; +use Imagick; +use Exception; /** * Draw an inline pie-chart directly from the available request parameters. */ class PieChart extends Inline { - public function render() + public function render($output = true) { $pie = new PieChartRenderer(); $pie->disableLegend(); @@ -44,6 +46,23 @@ class PieChart extends Inline { 'data' => $this->data, 'colors' => $this->colors, 'labels' => $this->labels )); $pie->setWidth($this->width)->setHeight($this->height); - echo $pie->render(); + if ($output) { + echo $pie->render(); + } else { + return $pie->render(); + } + } + + public function toPng() + { + if (! class_exists('Imagick')) { + // TODO: This is quick & dirty. 404? + throw new Exception('Cannot render PNGs without Imagick'); + } + $image = new Imagick(); + $image->readImageBlob($this->render(false)); + $image->setImageFormat('png24'); + $image->resizeImage($this->width, $this->height, imagick::FILTER_LANCZOS, 1); + echo $image; } } \ No newline at end of file diff --git a/library/Icinga/File/Pdf.php b/library/Icinga/File/Pdf.php index fd90a0299..77f5bf001 100644 --- a/library/Icinga/File/Pdf.php +++ b/library/Icinga/File/Pdf.php @@ -48,6 +48,7 @@ class Pdf extends DOMPDF $html = $layout->render(); $imgDir = Url::fromPath('img'); $html = preg_replace('~src="' . $imgDir . '/~', 'src="' . Icinga::app()->getBootstrapDirecory() . '/img/', $html); + $html = preg_replace('~src="/svg/chart.php(.*)"~', 'class="icon" src="http://master1.com/png/chart.php$1"', $html); $this->load_html($html); $this->render(); $this->stream( diff --git a/library/vendor/dompdf/dompdf_config.inc.php b/library/vendor/dompdf/dompdf_config.inc.php index 723b5c0dc..742b312b7 100644 --- a/library/vendor/dompdf/dompdf_config.inc.php +++ b/library/vendor/dompdf/dompdf_config.inc.php @@ -266,7 +266,7 @@ def("DOMPDF_ENABLE_PHP", false); * * @var bool */ -def("DOMPDF_ENABLE_JAVASCRIPT", true); +def("DOMPDF_ENABLE_JAVASCRIPT", false; /** * Enable remote file access @@ -285,7 +285,7 @@ def("DOMPDF_ENABLE_JAVASCRIPT", true); * * @var bool */ -def("DOMPDF_ENABLE_REMOTE", false); +def("DOMPDF_ENABLE_REMOTE", true); /** * The debug output log From 796a5977df4efe50733109ef072e6d7d65492ac2 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 22:49:49 +0000 Subject: [PATCH 54/55] /files: remove useless file --- files | 384 ---------------------------------------------------------- 1 file changed, 384 deletions(-) delete mode 100644 files diff --git a/files b/files deleted file mode 100644 index 8c743933a..000000000 --- a/files +++ /dev/null @@ -1,384 +0,0 @@ -./modules/doc/application/controllers/IndexController.php -./modules/doc/application/controllers/ModuleController.php -./modules/doc/library/Doc/DocParser.php -./modules/doc/library/Doc/Controller.php -./modules/doc/library/Doc/DocException.php -./modules/doc/library/Doc/MarkdownFileIterator.php -./modules/translation/application/clicommands/CompileCommand.php -./modules/translation/application/clicommands/RefreshCommand.php -./modules/translation/library/Translation/Cli/TranslationCommand.php -./modules/translation/library/Translation/Util/GettextTranslationHelper.php -./modules/monitoring/application/forms/Config/Backend/EditBackendForm.php -./modules/monitoring/application/forms/Config/Backend/CreateBackendForm.php -./modules/monitoring/application/forms/Config/ConfirmRemovalForm.php -./modules/monitoring/application/forms/Config/Instance/CreateInstanceForm.php -./modules/monitoring/application/forms/Config/Instance/EditInstanceForm.php -./modules/monitoring/application/forms/Command/DelayNotificationForm.php -./modules/monitoring/application/forms/Command/SubmitPassiveCheckResultForm.php -./modules/monitoring/application/forms/Command/CommandForm.php -./modules/monitoring/application/forms/Command/WithChildrenCommandForm.php -./modules/monitoring/application/forms/Command/CustomNotificationForm.php -./modules/monitoring/application/forms/Command/AcknowledgeForm.php -./modules/monitoring/application/forms/Command/CommentForm.php -./modules/monitoring/application/forms/Command/MultiCommandFlagForm.php -./modules/monitoring/application/forms/Command/RescheduleNextCheckForm.php -./modules/monitoring/application/forms/Command/ScheduleDowntimeForm.php -./modules/monitoring/application/forms/Command/SingleArgumentCommandForm.php -./modules/monitoring/application/forms/Command/DisableNotificationWithExpireForm.php -./modules/monitoring/application/views/helpers/MonitoringFlags.php -./modules/monitoring/application/views/helpers/MonitoringProperties.php -./modules/monitoring/application/views/helpers/CommandForm.php -./modules/monitoring/application/views/helpers/RuntimeVariables.php -./modules/monitoring/application/views/helpers/CheckPerformance.php -./modules/monitoring/application/views/helpers/PluginOutput.php -./modules/monitoring/application/views/helpers/Perfdata.php -./modules/monitoring/application/views/helpers/_RenderServicePerfdata.php -./modules/monitoring/application/views/helpers/SelectionToolbar.php -./modules/monitoring/application/views/helpers/ContactFlags.php -./modules/monitoring/application/views/helpers/ResolveMacros.php -./modules/monitoring/application/views/helpers/MonitoringState.php -./modules/monitoring/application/views/helpers/ResolveComments.php -./modules/monitoring/application/clicommands/NrpeCommand.php -./modules/monitoring/application/clicommands/ConferenceCommand.php -./modules/monitoring/application/clicommands/ListCommand.php -./modules/monitoring/application/controllers/ShowController.php -./modules/monitoring/application/controllers/ConfigController.php -./modules/monitoring/application/controllers/MultiController.php -./modules/monitoring/application/controllers/ListController.php -./modules/monitoring/application/controllers/CommandController.php -./modules/monitoring/application/controllers/MonitoringCommands.php -./modules/monitoring/application/controllers/ChartController.php -./modules/monitoring/application/controllers/TimelineController.php -./modules/monitoring/application/controllers/TacticalController.php -./modules/monitoring/application/controllers/ProcessController.php -./modules/monitoring/library/Monitoring/DataView/Contactgroup.php -./modules/monitoring/library/Monitoring/DataView/Notification.php -./modules/monitoring/library/Monitoring/DataView/Comment.php -./modules/monitoring/library/Monitoring/DataView/Customvar.php -./modules/monitoring/library/Monitoring/DataView/EventHistory.php -./modules/monitoring/library/Monitoring/DataView/StatusSummary.php -./modules/monitoring/library/Monitoring/DataView/DataView.php -./modules/monitoring/library/Monitoring/DataView/Runtimesummary.php -./modules/monitoring/library/Monitoring/DataView/Servicegroup.php -./modules/monitoring/library/Monitoring/DataView/Runtimevariables.php -./modules/monitoring/library/Monitoring/DataView/Contact.php -./modules/monitoring/library/Monitoring/DataView/Programstatus.php -./modules/monitoring/library/Monitoring/DataView/StateHistorySummary.php -./modules/monitoring/library/Monitoring/DataView/Downtime.php -./modules/monitoring/library/Monitoring/DataView/Groupsummary.php -./modules/monitoring/library/Monitoring/DataView/Hostgroup.php -./modules/monitoring/library/Monitoring/DataView/HostStatus.php -./modules/monitoring/library/Monitoring/DataView/ServiceStatus.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusdatQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ContactgroupQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ServicegroupsummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostgroupQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/CommentQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/DowntimeQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusSummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/GroupsummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ContactQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ServicegroupQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostlistQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php -./modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ServicelistQuery.php -./modules/monitoring/library/Monitoring/Backend/Livestatus/Query/StatusQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationhistoryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeendhistoryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusSummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimevariablesQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenthistoryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/StateHistorySummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/AllcontactsQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimestarthistoryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimesummaryQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php -./modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php -./modules/monitoring/library/Monitoring/Environment.php -./modules/monitoring/library/Monitoring/Controller.php -./modules/monitoring/library/Monitoring/Timeline/TimeEntry.php -./modules/monitoring/library/Monitoring/Timeline/TimeRange.php -./modules/monitoring/library/Monitoring/Timeline/TimeLine.php -./modules/monitoring/library/Monitoring/Object/Service.php -./modules/monitoring/library/Monitoring/Object/Host.php -./modules/monitoring/library/Monitoring/Object/AbstractObject.php -./modules/monitoring/library/Monitoring/Filter/Type/StatusFilter.php -./modules/monitoring/library/Monitoring/Filter/Registry.php -./modules/monitoring/library/Monitoring/Filter/UrlViewFilter.php -./modules/monitoring/library/Monitoring/Exception/UnsupportedBackendException.php -./modules/monitoring/library/Monitoring/Web/Widget/TimelineIntervalBox.php -./modules/monitoring/library/Monitoring/Web/Hook/TimelineProvider.php -./modules/monitoring/library/Monitoring/Web/Hook/TopBar.php -./modules/monitoring/library/Monitoring/Command/SubmitPassiveCheckresultCommand.php -./modules/monitoring/library/Monitoring/Command/AcknowledgeCommand.php -./modules/monitoring/library/Monitoring/Command/ScheduleDowntimeCommand.php -./modules/monitoring/library/Monitoring/Command/ScheduleCheckCommand.php -./modules/monitoring/library/Monitoring/Command/DisableNotificationWithExpireCommand.php -./modules/monitoring/library/Monitoring/Command/SingleArgumentCommand.php -./modules/monitoring/library/Monitoring/Command/AddCommentCommand.php -./modules/monitoring/library/Monitoring/Command/CustomNotificationCommand.php -./modules/monitoring/library/Monitoring/Command/DelayNotificationCommand.php -./modules/monitoring/library/Monitoring/Plugin.php -./modules/monitoring/library/Monitoring/Cli/CliUtils.php -./modules/monitoring/library/Monitoring/Backend.php -./modules/monitoring/library/Monitoring/Plugin/Perfdata.php -./modules/monitoring/library/Monitoring/Plugin/PerfdataSet.php -./modules/monitoring/run.php -./modules/monitoring/configuration.php -./modules/monitoring/bin/action/list.inc.php -./etc/module_skeleton/application/controllers/IndexController.php -./application/forms/Authentication/LoginForm.php -./application/forms/Config/GeneralForm.php -./application/forms/Config/Authentication/LdapBackendForm.php -./application/forms/Config/Authentication/ReorderForm.php -./application/forms/Config/Authentication/BaseBackendForm.php -./application/forms/Config/Authentication/DbBackendForm.php -./application/forms/Config/LoggingForm.php -./application/forms/Config/ConfirmRemovalForm.php -./application/forms/Config/Resource/CreateResourceForm.php -./application/forms/Config/Resource/EditResourceForm.php -./application/forms/TestForm.php -./application/forms/Dashboard/AddUrlForm.php -./application/forms/Preference/GeneralForm.php -./application/views/helpers/FormNumber.php -./application/views/helpers/DateFormat.php -./application/views/helpers/FormDateTime.php -./application/views/helpers/FormTriStateCheckbox.php -./application/views/helpers/Util.php -./application/clicommands/HelpCommand.php -./application/clicommands/ModuleCommand.php -./application/clicommands/AutocompleteCommand.php -./application/clicommands/WebCommand.php -./application/controllers/ConfigController.php -./application/controllers/ListController.php -./application/controllers/IndexController.php -./application/controllers/LayoutController.php -./application/controllers/PreferenceController.php -./application/controllers/DashboardController.php -./application/controllers/FilterController.php -./application/controllers/StaticController.php -./application/controllers/SearchController.php -./application/controllers/ErrorController.php -./application/controllers/AuthenticationController.php -./library/Icinga/Logger/Logger.php -./library/Icinga/Logger/Writer/StreamWriter.php -./library/Icinga/Logger/Writer/SyslogWriter.php -./library/Icinga/Logger/LogWriter.php -./library/Icinga/User/Preferences.php -./library/Icinga/User/Message.php -./library/Icinga/User/Preferences/Store/IniStore.php -./library/Icinga/User/Preferences/Store/DbStore.php -./library/Icinga/User/Preferences/PreferencesStore.php -./library/Icinga/Authentication/UserBackend.php -./library/Icinga/Authentication/Backend/DbUserBackend.php -./library/Icinga/Authentication/Backend/LdapUserBackend.php -./library/Icinga/Authentication/Membership.php -./library/Icinga/Authentication/Manager.php -./library/Icinga/Authentication/AdmissionLoader.php -./library/Icinga/Authentication/AuthChain.php -./library/Icinga/Data/Db/Query.php -./library/Icinga/Data/Db/TreeToSqlParser.php -./library/Icinga/Data/Db/Connection.php -./library/Icinga/Data/PivotTable.php -./library/Icinga/Data/DatasourceInterface.php -./library/Icinga/Data/DataArray/Query.php -./library/Icinga/Data/DataArray/Datasource.php -./library/Icinga/Data/ResourceFactory.php -./library/Icinga/Data/BaseQuery.php -./library/Icinga/File/Pdf.php -./library/Icinga/File/Csv.php -./library/Icinga/File/Csv/Query.php -./library/Icinga/Test/DbTest.php -./library/Icinga/Test/BaseTestCase.php -./library/Icinga/Test/FormTest.php -./library/Icinga/Protocol/Ldap/Root.php -./library/Icinga/Protocol/Ldap/Query.php -./library/Icinga/Protocol/Ldap/Exception.php -./library/Icinga/Protocol/Ldap/LdapUtils.php -./library/Icinga/Protocol/Ldap/Node.php -./library/Icinga/Protocol/Ldap/Connection.php -./library/Icinga/Protocol/File/Query.php -./library/Icinga/Protocol/File/Reader.php -./library/Icinga/Protocol/Statusdat/Parser.php -./library/Icinga/Protocol/Statusdat/Query.php -./library/Icinga/Protocol/Statusdat/Query/IQueryPart.php -./library/Icinga/Protocol/Statusdat/Query/Group.php -./library/Icinga/Protocol/Statusdat/Query/Expression.php -./library/Icinga/Protocol/Statusdat/View/AccessorStrategy.php -./library/Icinga/Protocol/Statusdat/View/MonitoringObjectList.php -./library/Icinga/Protocol/Statusdat/ObjectContainer.php -./library/Icinga/Protocol/Statusdat/Exception/ParsingException.php -./library/Icinga/Protocol/Statusdat/Reader.php -./library/Icinga/Protocol/Statusdat/IReader.php -./library/Icinga/Protocol/Statusdat/PrintableObject.php -./library/Icinga/Protocol/Statusdat/TreeToStatusdatQueryParser.php -./library/Icinga/Protocol/Statusdat/RuntimeStateContainer.php -./library/Icinga/Protocol/Nrpe/Packet.php -./library/Icinga/Protocol/Nrpe/Connection.php -./library/Icinga/Protocol/Livestatus/Query.php -./library/Icinga/Protocol/Livestatus/Connection.php -./library/Icinga/Protocol/Commandpipe/Transport/Transport.php -./library/Icinga/Protocol/Commandpipe/Transport/LocalPipe.php -./library/Icinga/Protocol/Commandpipe/Transport/SecureShell.php -./library/Icinga/Protocol/Commandpipe/Comment.php -./library/Icinga/Protocol/Commandpipe/Exception/InvalidCommandException.php -./library/Icinga/Protocol/Commandpipe/PropertyModifier.php -./library/Icinga/Protocol/Commandpipe/Command.php -./library/Icinga/Protocol/Commandpipe/CommandPipe.php -./library/Icinga/Application/Platform.php -./library/Icinga/Application/Benchmark.php -./library/Icinga/Application/functions.php -./library/Icinga/Application/LegacyWeb.php -./library/Icinga/Application/Config.php -./library/Icinga/Application/EmbeddedWeb.php -./library/Icinga/Application/ApplicationBootstrap.php -./library/Icinga/Application/Cli.php -./library/Icinga/Application/webrouter.php -./library/Icinga/Application/Modules/Module.php -./library/Icinga/Application/Modules/Manager.php -./library/Icinga/Application/Loader.php -./library/Icinga/Application/Icinga.php -./library/Icinga/Application/Web.php -./library/Icinga/Chart/Primitive/Animation.php -./library/Icinga/Chart/Primitive/Text.php -./library/Icinga/Chart/Primitive/Animatable.php -./library/Icinga/Chart/Primitive/Drawable.php -./library/Icinga/Chart/Primitive/Circle.php -./library/Icinga/Chart/Primitive/Styleable.php -./library/Icinga/Chart/Primitive/RawElement.php -./library/Icinga/Chart/Primitive/Rect.php -./library/Icinga/Chart/Primitive/Line.php -./library/Icinga/Chart/Primitive/Canvas.php -./library/Icinga/Chart/Primitive/PieSlice.php -./library/Icinga/Chart/Primitive/Path.php -./library/Icinga/Chart/Graph/LineGraph.php -./library/Icinga/Chart/Graph/StackedGraph.php -./library/Icinga/Chart/Graph/BarGraph.php -./library/Icinga/Chart/Axis.php -./library/Icinga/Chart/Palette.php -./library/Icinga/Chart/Unit/AxisUnit.php -./library/Icinga/Chart/Unit/LinearUnit.php -./library/Icinga/Chart/Unit/StaticAxis.php -./library/Icinga/Chart/Unit/CalendarUnit.php -./library/Icinga/Chart/PieChart.php -./library/Icinga/Chart/GridChart.php -./library/Icinga/Chart/SVGRenderer.php -./library/Icinga/Chart/Legend.php -./library/Icinga/Chart/Inline/PieChart.php -./library/Icinga/Chart/Inline/Inline.php -./library/Icinga/Chart/Chart.php -./library/Icinga/Chart/Render/RenderContext.php -./library/Icinga/Chart/Render/LayoutBox.php -./library/Icinga/Config/IniEditor.php -./library/Icinga/Config/PreservingIniWriter.php -./library/Icinga/User.php -./library/Icinga/Filter/Query/Tree.php -./library/Icinga/Filter/Query/Node.php -./library/Icinga/Filter/FilterAttribute.php -./library/Icinga/Filter/Type/FilterType.php -./library/Icinga/Filter/Type/BooleanFilter.php -./library/Icinga/Filter/Type/TextFilter.php -./library/Icinga/Filter/Type/TimeRangeSpecifier.php -./library/Icinga/Filter/QueryProposer.php -./library/Icinga/Filter/Registry.php -./library/Icinga/Filter/Filter.php -./library/Icinga/Filter/Filterable.php -./library/Icinga/Filter/Domain.php -./library/Icinga/Exception/NotWritableError.php -./library/Icinga/Exception/MissingParameterException.php -./library/Icinga/Exception/NotImplementedError.php -./library/Icinga/Exception/ConfigurationError.php -./library/Icinga/Exception/NotReadableError.php -./library/Icinga/Exception/SystemPermissionException.php -./library/Icinga/Exception/ProgrammingError.php -./library/Icinga/Web/JavaScript.php -./library/Icinga/Web/Notification.php -./library/Icinga/Web/MenuItem.php -./library/Icinga/Web/Widget/Dashboard.php -./library/Icinga/Web/Widget/FilterBox.php -./library/Icinga/Web/Widget/AlertMessageBox.php -./library/Icinga/Web/Widget/Tabextension/DashboardAction.php -./library/Icinga/Web/Widget/Tabextension/BasketAction.php -./library/Icinga/Web/Widget/Tabextension/Tabextension.php -./library/Icinga/Web/Widget/Tabextension/OutputFormat.php -./library/Icinga/Web/Widget/Chart/InlinePie.php -./library/Icinga/Web/Widget/Chart/HistoryColorGrid.php -./library/Icinga/Web/Widget/AbstractWidget.php -./library/Icinga/Web/Widget/FilterBadgeRenderer.php -./library/Icinga/Web/Widget/Dashboard/Component.php -./library/Icinga/Web/Widget/Dashboard/Pane.php -./library/Icinga/Web/Widget/Tabs.php -./library/Icinga/Web/Widget/Tab.php -./library/Icinga/Web/Widget/Widget.php -./library/Icinga/Web/Widget/SortBox.php -./library/Icinga/Web/Hook.php -./library/Icinga/Web/View/helpers/generic.php -./library/Icinga/Web/View/helpers/url.php -./library/Icinga/Web/View/helpers/format.php -./library/Icinga/Web/Menu.php -./library/Icinga/Web/Session.php -./library/Icinga/Web/Paginator/ScrollingStyle/SlidingWithBorder.php -./library/Icinga/Web/Paginator/Adapter/QueryAdapter.php -./library/Icinga/Web/ViewStream.php -./library/Icinga/Web/Url.php -./library/Icinga/Web/Session/SessionNamespace.php -./library/Icinga/Web/Session/Session.php -./library/Icinga/Web/Session/PhpSession.php -./library/Icinga/Web/StyleSheet.php -./library/Icinga/Web/Hook/Ticket.php -./library/Icinga/Web/Hook/Configuration/ConfigurationTabInterface.php -./library/Icinga/Web/Hook/Configuration/ConfigurationTab.php -./library/Icinga/Web/Hook/Configuration/ConfigurationTabBuilder.php -./library/Icinga/Web/Hook/TopBar.php -./library/Icinga/Web/Hook/Grapher.php -./library/Icinga/Web/Request.php -./library/Icinga/Web/View.php -./library/Icinga/Web/Widget.php -./library/Icinga/Web/Controller/ActionController.php -./library/Icinga/Web/Controller/BaseConfigController.php -./library/Icinga/Web/Controller/BasePreferenceController.php -./library/Icinga/Web/Controller/ControllerTabCollector.php -./library/Icinga/Web/LessCompiler.php -./library/Icinga/Web/Form.php -./library/Icinga/Web/Form/Element/Number.php -./library/Icinga/Web/Form/Element/DateTimePicker.php -./library/Icinga/Web/Form/Element/TriStateCheckbox.php -./library/Icinga/Web/Form/Element/Note.php -./library/Icinga/Web/Form/Decorator/ConditionalHidden.php -./library/Icinga/Web/Form/Decorator/BootstrapForm.php -./library/Icinga/Web/Form/Decorator/HelpText.php -./library/Icinga/Web/Form/Validator/DateFormatValidator.php -./library/Icinga/Web/Form/Validator/TriStateValidator.php -./library/Icinga/Web/Form/Validator/DateTimeValidator.php -./library/Icinga/Web/Form/Validator/TimeFormatValidator.php -./library/Icinga/Web/Form/Validator/WritablePathValidator.php -./library/Icinga/Web/Form/InvalidCSRFTokenException.php -./library/Icinga/Cli/Documentation/CommentParser.php -./library/Icinga/Cli/Params.php -./library/Icinga/Cli/Documentation.php -./library/Icinga/Cli/Screen/AnsiScreen.php -./library/Icinga/Cli/Loader.php -./library/Icinga/Cli/Command.php -./library/Icinga/Cli/Screen.php -./library/Icinga/Util/File.php -./library/Icinga/Util/Dimension.php -./library/Icinga/Util/DateTimeFactory.php -./library/Icinga/Util/Color.php -./library/Icinga/Util/String.php -./library/Icinga/Util/Format.php -./library/Icinga/Util/ConfigAwareFactory.php -./library/Icinga/Util/Translator.php - From cf42ffbafa2eb571e4298f4323ed1071898d80d8 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 20 May 2014 22:56:01 +0000 Subject: [PATCH 55/55] Parsedown: version 1.0 released --- library/vendor/Parsedown/Parsedown.php | 429 ++++++++++++++----------- library/vendor/Parsedown/SOURCE | 2 +- 2 files changed, 244 insertions(+), 187 deletions(-) diff --git a/library/vendor/Parsedown/Parsedown.php b/library/vendor/Parsedown/Parsedown.php index 20db13475..92f3dd897 100644 --- a/library/vendor/Parsedown/Parsedown.php +++ b/library/vendor/Parsedown/Parsedown.php @@ -29,6 +29,9 @@ class Parsedown function text($text) { + # make sure no definitions are set + $this->Definitions = array(); + # standardize line breaks $text = str_replace("\r\n", "\n", $text); $text = str_replace("\r", "\n", $text); @@ -48,9 +51,6 @@ class Parsedown # trim line breaks $markup = trim($markup, "\n"); - # clean up - $this->definitions = array(); - return $markup; } @@ -58,6 +58,8 @@ class Parsedown # Setters # + private $breaksEnabled; + function setBreaksEnabled($breaksEnabled) { $this->breaksEnabled = $breaksEnabled; @@ -65,13 +67,11 @@ class Parsedown return $this; } - private $breaksEnabled; - # - # Blocks + # Lines # - protected $blockMarkers = array( + protected $BlockTypes = array( '#' => array('Atx'), '*' => array('Rule', 'List'), '+' => array('List'), @@ -87,24 +87,31 @@ class Parsedown '8' => array('List'), '9' => array('List'), ':' => array('Table'), - '<' => array('Markup'), + '<' => array('Comment', 'Markup'), '=' => array('Setext'), '>' => array('Quote'), - '[' => array('Reference'), '_' => array('Rule'), '`' => array('FencedCode'), '|' => array('Table'), '~' => array('FencedCode'), ); - protected $definitionMarkers = array( + # ~ + + protected $DefinitionTypes = array( '[' => array('Reference'), ); + # ~ + protected $unmarkedBlockTypes = array( 'CodeBlock', ); + # + # Blocks + # + private function lines(array $lines) { $CurrentBlock = null; @@ -134,7 +141,7 @@ class Parsedown $Line = array('body' => $line, 'indent' => $indent, 'text' => $text); - # Multiline block types define "addTo" methods. + # ~ if (isset($CurrentBlock['incomplete'])) { @@ -161,17 +168,15 @@ class Parsedown $marker = $text[0]; - # Definitions - - if (isset($this->definitionMarkers[$marker])) + if (isset($this->DefinitionTypes[$marker])) { - foreach ($this->definitionMarkers[$marker] as $definitionType) + foreach ($this->DefinitionTypes[$marker] as $definitionType) { $Definition = $this->{'identify'.$definitionType}($Line, $CurrentBlock); if (isset($Definition)) { - $this->definitions[$definitionType][$Definition['id']] = $Definition['data']; + $this->Definitions[$definitionType][$Definition['id']] = $Definition['data']; continue 2; } @@ -182,9 +187,9 @@ class Parsedown $blockTypes = $this->unmarkedBlockTypes; - if (isset($this->blockMarkers[$marker])) + if (isset($this->BlockTypes[$marker])) { - foreach ($this->blockMarkers[$marker] as $blockType) + foreach ($this->BlockTypes[$marker] as $blockType) { $blockTypes []= $blockType; } @@ -195,23 +200,19 @@ class Parsedown foreach ($blockTypes as $blockType) { - # Block types define "identify" methods. - $Block = $this->{'identify'.$blockType}($Line, $CurrentBlock); if (isset($Block)) { $Block['type'] = $blockType; - if ( ! isset($Block['identified'])) # ยป + if ( ! isset($Block['identified'])) { $Elements []= $CurrentBlock['element']; $Block['identified'] = true; } - # Multiline block types define "addTo" methods. - if (method_exists($this, 'addTo'.$blockType)) { $Block['incomplete'] = true; @@ -225,7 +226,7 @@ class Parsedown # ~ - if ($CurrentBlock['type'] === 'Paragraph' and ! isset($CurrentBlock['interrupted'])) + if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted'])) { $CurrentBlock['element']['text'] .= "\n".$text; } @@ -233,15 +234,9 @@ class Parsedown { $Elements []= $CurrentBlock['element']; - $CurrentBlock = array( - 'type' => 'Paragraph', - 'identified' => true, - 'element' => array( - 'name' => 'p', - 'text' => $text, - 'handler' => 'line', - ), - ); + $CurrentBlock = $this->buildParagraph($Line); + + $CurrentBlock['identified'] = true; } } @@ -296,15 +291,22 @@ class Parsedown } # - # Rule + # Code - protected function identifyRule($Line) + protected function identifyCodeBlock($Line) { - if (preg_match('/^(['.$Line['text'][0].'])([ ]{0,2}\1){2,}[ ]*$/', $Line['text'])) + if ($Line['indent'] >= 4) { + $text = substr($Line['body'], 4); + $Block = array( 'element' => array( - 'name' => 'hr' + 'name' => 'pre', + 'handler' => 'element', + 'text' => array( + 'name' => 'code', + 'text' => $text, + ), ), ); @@ -312,104 +314,72 @@ class Parsedown } } - # - # Reference - - protected function identifyReference($Line) + protected function addToCodeBlock($Line, $Block) { - if (preg_match('/^\[(.+?)\]:[ ]*?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches)) + if ($Line['indent'] >= 4) { - $Definition = array( - 'id' => strtolower($matches[1]), - 'data' => array( - 'url' => $matches[2], - ), - ); - - if (isset($matches[3])) + if (isset($Block['interrupted'])) { - $Definition['data']['title'] = $matches[3]; + $Block['element']['text']['text'] .= "\n"; + + unset($Block['interrupted']); } - return $Definition; - } - } + $Block['element']['text']['text'] .= "\n"; - # - # Setext + $text = substr($Line['body'], 4); - protected function identifySetext($Line, array $Block = null) - { - if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted'])) - { - return; - } - - if (chop($Line['text'], $Line['text'][0]) === '') - { - $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2'; + $Block['element']['text']['text'] .= $text; return $Block; } } - # - # Markup - - protected function identifyMarkup($Line) + protected function completeCodeBlock($Block) { - if (preg_match('/^<(\w[\w\d]*)(?:[ ][^>\/]*)?(\/?)[ ]*>/', $Line['text'], $matches)) - { - if (in_array($matches[1], $this->textLevelElements)) - { - return; - } + $text = $Block['element']['text']['text']; + $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8'); + + $Block['element']['text']['text'] = $text; + + return $Block; + } + + # + # Comment + + protected function identifyComment($Line) + { + if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!') + { $Block = array( 'element' => $Line['body'], ); - if ($matches[2] or $matches[1] === 'hr' or preg_match('/<\/'.$matches[1].'>[ ]*$/', $Line['text'])) + if (preg_match('/-->$/', $Line['text'])) { $Block['closed'] = true; } - else - { - $Block['depth'] = 0; - $Block['start'] = '<'.$matches[1].'>'; - $Block['end'] = ''; - } return $Block; } } - protected function addToMarkup($Line, array $Block) + protected function addToComment($Line, array $Block) { if (isset($Block['closed'])) { return; } - if (stripos($Line['text'], $Block['start']) !== false) # opening tag - { - $Block['depth'] ++; - } + $Block['element'] .= "\n" . $Line['body']; - if (stripos($Line['text'], $Block['end']) !== false) # closing tag + if (preg_match('/-->$/', $Line['text'])) { - if ($Block['depth'] > 0) - { - $Block['depth'] --; - } - else - { - $Block['closed'] = true; - } + $Block['closed'] = true; } - $Block['element'] .= "\n".$Line['body']; - return $Block; } @@ -610,12 +580,106 @@ class Parsedown } } + # + # Rule + + protected function identifyRule($Line) + { + if (preg_match('/^(['.$Line['text'][0].'])([ ]{0,2}\1){2,}[ ]*$/', $Line['text'])) + { + $Block = array( + 'element' => array( + 'name' => 'hr' + ), + ); + + return $Block; + } + } + + # + # Setext + + protected function identifySetext($Line, array $Block = null) + { + if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) + { + return; + } + + if (chop($Line['text'], $Line['text'][0]) === '') + { + $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2'; + + return $Block; + } + } + + # + # Markup + + protected function identifyMarkup($Line) + { + if (preg_match('/^<(\w[\w\d]*)(?:[ ][^>\/]*)?(\/?)[ ]*>/', $Line['text'], $matches)) + { + if (in_array($matches[1], $this->textLevelElements)) + { + return; + } + + $Block = array( + 'element' => $Line['body'], + ); + + if ($matches[2] or $matches[1] === 'hr' or preg_match('/<\/'.$matches[1].'>[ ]*$/', $Line['text'])) + { + $Block['closed'] = true; + } + else + { + $Block['depth'] = 0; + $Block['name'] = $matches[1]; + } + + return $Block; + } + } + + protected function addToMarkup($Line, array $Block) + { + if (isset($Block['closed'])) + { + return; + } + + if (preg_match('/<'.$Block['name'].'([ ][^\/]+)?>/', $Line['text'])) # opening tag + { + $Block['depth'] ++; + } + + if (stripos($Line['text'], '') !== false) # closing tag + { + if ($Block['depth'] > 0) + { + $Block['depth'] --; + } + else + { + $Block['closed'] = true; + } + } + + $Block['element'] .= "\n".$Line['body']; + + return $Block; + } + # # Table protected function identifyTable($Line, array $Block = null) { - if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted'])) + if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) { return; } @@ -766,57 +830,42 @@ class Parsedown } # - # Code + # Definitions + # - protected function identifyCodeBlock($Line) + protected function identifyReference($Line) { - if ($Line['indent'] >= 4) + if (preg_match('/^\[(.+?)\]:[ ]*?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches)) { - $text = substr($Line['body'], 4); - - $Block = array( - 'element' => array( - 'name' => 'pre', - 'handler' => 'element', - 'text' => array( - 'name' => 'code', - 'text' => $text, - ), + $Definition = array( + 'id' => strtolower($matches[1]), + 'data' => array( + 'url' => $matches[2], ), ); - return $Block; - } - } - - protected function addToCodeBlock($Line, $Block) - { - if ($Line['indent'] >= 4) - { - if (isset($Block['interrupted'])) + if (isset($matches[3])) { - $Block['element']['text']['text'] .= "\n"; - - unset($Block['interrupted']); + $Definition['data']['title'] = $matches[3]; } - $Block['element']['text']['text'] .= "\n"; - - $text = substr($Line['body'], 4); - - $Block['element']['text']['text'] .= $text; - - return $Block; + return $Definition; } } - protected function completeCodeBlock($Block) + # + # ~ + # + + protected function buildParagraph($Line) { - $text = $Block['element']['text']['text']; - - $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8'); - - $Block['element']['text']['text'] = $text; + $Block = array( + 'element' => array( + 'name' => 'p', + 'text' => $Line['text'], + 'handler' => 'line', + ), + ); return $Block; } @@ -825,7 +874,7 @@ class Parsedown # ~ # - private function element(array $Element) + protected function element(array $Element) { $markup = '<'.$Element['name']; @@ -860,7 +909,7 @@ class Parsedown return $markup; } - private function elements(array $Elements) + protected function elements(array $Elements) { $markup = ''; @@ -873,7 +922,7 @@ class Parsedown $markup .= "\n"; - if (is_string($Element)) # because of markup + if (is_string($Element)) # because of Markup { $markup .= $Element; @@ -892,7 +941,7 @@ class Parsedown # Spans # - protected $spanMarkers = array( + protected $SpanTypes = array( '!' => array('Link'), # ? '&' => array('Ampersand'), '*' => array('Emphasis'), @@ -905,8 +954,14 @@ class Parsedown '\\' => array('EscapeSequence'), ); + # ~ + protected $spanMarkerList = '*_!&[spanMarkerList)) + while ($excerpt = strpbrk($remainder, $this->spanMarkerList)) { - $marker = $markedExcerpt[0]; + $marker = $excerpt[0]; $markerPosition += strpos($remainder, $marker); - foreach ($this->spanMarkers[$marker] as $spanType) + $Excerpt = array('text' => $excerpt, 'context' => $text); + + foreach ($this->SpanTypes[$marker] as $spanType) { $handler = 'identify'.$spanType; - $Span = $this->$handler($markedExcerpt, $text); + $Span = $this->$handler($Excerpt); if ( ! isset($Span)) { @@ -950,7 +1007,7 @@ class Parsedown $markup .= $this->readPlainText($plainText); - $markup .= isset($Span['element']) ? $this->element($Span['element']) : $Span['markup']; + $markup .= isset($Span['markup']) ? $Span['markup'] : $this->element($Span['element']); $text = substr($text, $Span['position'] + $Span['extent']); @@ -961,7 +1018,7 @@ class Parsedown continue 2; } - $remainder = substr($markedExcerpt, 1); + $remainder = substr($excerpt, 1); $markerPosition ++; } @@ -975,14 +1032,14 @@ class Parsedown # ~ # - protected function identifyUrl($excerpt, $text) + protected function identifyUrl($Excerpt) { - if ( ! isset($excerpt[1]) or $excerpt[1] !== '/') + if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '/') { return; } - if (preg_match('/\bhttps?:[\/]{2}[^\s]+\b\/*/ui', $text, $matches, PREG_OFFSET_CAPTURE)) + if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE)) { $url = str_replace(array('&', '<'), array('&', '<'), $matches[0][0]); @@ -1000,9 +1057,9 @@ class Parsedown } } - protected function identifyAmpersand($excerpt) + protected function identifyAmpersand($Excerpt) { - if ( ! preg_match('/^&#?\w+;/', $excerpt)) + if ( ! preg_match('/^&#?\w+;/', $Excerpt['text'])) { return array( 'markup' => '&', @@ -1011,14 +1068,14 @@ class Parsedown } } - protected function identifyStrikethrough($excerpt) + protected function identifyStrikethrough($Excerpt) { - if ( ! isset($excerpt[1])) + if ( ! isset($Excerpt['text'][1])) { return; } - if ($excerpt[1] === $excerpt[0] and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $excerpt, $matches)) + if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches)) { return array( 'extent' => strlen($matches[0]), @@ -1031,12 +1088,12 @@ class Parsedown } } - protected function identifyEscapeSequence($excerpt) + protected function identifyEscapeSequence($Excerpt) { - if (in_array($excerpt[1], $this->specialCharacters)) + if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters)) { return array( - 'markup' => $excerpt[1], + 'markup' => $Excerpt['text'][1], 'extent' => 2, ); } @@ -1050,9 +1107,9 @@ class Parsedown ); } - protected function identifyUrlTag($excerpt) + protected function identifyUrlTag($Excerpt) { - if (strpos($excerpt, '>') !== false and preg_match('/^<(https?:[\/]{2}[^\s]+?)>/i', $excerpt, $matches)) + if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(https?:[\/]{2}[^\s]+?)>/i', $Excerpt['text'], $matches)) { $url = str_replace(array('&', '<'), array('&', '<'), $matches[1]); @@ -1069,9 +1126,9 @@ class Parsedown } } - protected function identifyEmailTag($excerpt) + protected function identifyEmailTag($Excerpt) { - if (strpos($excerpt, '>') !== false and preg_match('/^<(\S+?@\S+?)>/', $excerpt, $matches)) + if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\S+?@\S+?)>/', $Excerpt['text'], $matches)) { return array( 'extent' => strlen($matches[0]), @@ -1086,9 +1143,9 @@ class Parsedown } } - protected function identifyTag($excerpt) + protected function identifyTag($Excerpt) { - if (strpos($excerpt, '>') !== false and preg_match('/^<\/?\w.*?>/', $excerpt, $matches)) + if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<\/?\w.*?>/', $Excerpt['text'], $matches)) { return array( 'markup' => $matches[0], @@ -1097,11 +1154,11 @@ class Parsedown } } - protected function identifyInlineCode($excerpt) + protected function identifyInlineCode($Excerpt) { - $marker = $excerpt[0]; + $marker = $Excerpt['text'][0]; - if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(? $matches[1], 'label' => strtolower($matches[1])); $extent += strlen($matches[0]); - $substring = substr($excerpt, $extent); + $substring = substr($Excerpt['text'], $extent); - if (preg_match('/^\s*\[(.+?)\]/', $substring, $matches)) + if (preg_match('/^\s*\[([^][]+)\]/', $substring, $matches)) { $Link['label'] = strtolower($matches[1]); - if (isset($this->definitions['Reference'][$Link['label']])) + if (isset($this->Definitions['Reference'][$Link['label']])) { - $Link += $this->definitions['Reference'][$Link['label']]; + $Link += $this->Definitions['Reference'][$Link['label']]; $extent += strlen($matches[0]); } @@ -1143,9 +1200,9 @@ class Parsedown return; } } - elseif (isset($this->definitions['Reference'][$Link['label']])) + elseif (isset($this->Definitions['Reference'][$Link['label']])) { - $Link += $this->definitions['Reference'][$Link['label']]; + $Link += $this->Definitions['Reference'][$Link['label']]; if (preg_match('/^[ ]*\[\]/', $substring, $matches)) { @@ -1175,7 +1232,7 @@ class Parsedown $url = str_replace(array('&', '<'), array('&', '<'), $Link['url']); - if ($excerpt[0] === '!') + if ($Excerpt['text'][0] === '!') { $Element = array( 'name' => 'img', @@ -1208,20 +1265,20 @@ class Parsedown ); } - protected function identifyEmphasis($excerpt) + protected function identifyEmphasis($Excerpt) { - if ( ! isset($excerpt[1])) + if ( ! isset($Excerpt['text'][1])) { return; } - $marker = $excerpt[0]; + $marker = $Excerpt['text'][0]; - if ($excerpt[1] === $marker and preg_match($this->strongRegex[$marker], $excerpt, $matches)) + if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches)) { $emphasis = 'strong'; } - elseif (preg_match($this->emRegex[$marker], $excerpt, $matches)) + elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches)) { $emphasis = 'em'; } @@ -1313,7 +1370,7 @@ class Parsedown # Fields # - protected $definitions; + protected $Definitions; # # Read-only @@ -1322,12 +1379,12 @@ class Parsedown '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', ); - protected $strongRegex = array( + protected $StrongRegex = array( '*' => '/^[*]{2}((?:[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s', '_' => '/^__((?:[^_]|_[^_]*_)+?)__(?!_)/us', ); - protected $emRegex = array( + protected $EmRegex = array( '*' => '/^[*]((?:[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', '_' => '/^_((?:[^_]|__[^_]*__)+?)_(?!_)\b/us', ); diff --git a/library/vendor/Parsedown/SOURCE b/library/vendor/Parsedown/SOURCE index 59f79409d..c5a2c7c28 100644 --- a/library/vendor/Parsedown/SOURCE +++ b/library/vendor/Parsedown/SOURCE @@ -1,4 +1,4 @@ -RELEASE=1.0.0-rc.4 +RELEASE=1.0.0 FILENAME=parsedown-$RELEASE DESTINATION=. wget -O ${FILENAME}.tar.gz https://github.com/erusev/parsedown/archive/${RELEASE}.tar.gz