Icinga / icinga2

The core of our monitoring platform with a powerful configuration language and REST API.
https://icinga.com/docs/icinga2/latest
GNU General Public License v2.0
2.03k stars 579 forks source link

assign where rule and apply Service evaluation order #7012

Closed Gnoale closed 5 years ago

Gnoale commented 5 years ago

Current Behavior

I have two family of BGP services to check :

One with a simple array of description in the host definition with a variable vars.os = junos and an apply Service rule based on the assign rule host.vars.bgp && host.vars.os == "junos"

object Host "host-junos" {
  address = "1.1.1.1"
  check_command = "hostalive"
  vars.bgp = ["desc1", "desc3"]
  vars.os = "junos"
}

/* Junos BGP check */
apply Service "BGP peer - " for (description in host.vars.bgp) {
  import "generic-service"
  check_command = "check-junos-bgp-state"
  vars.description = description
  assign where host.vars.bgp && host.vars.os == "junos"
}

Another host definition with an array of array of bgp parameter to check and an apply Service rule associated based on the assign rule host.vars.bgp && host.vars.os == "brocade"

object Host "host-brocade" {
  address = "2.2.2.2"
  check_command = "hostalive"
  }
  vars.bgp = {
  bgp["desc1"] = {
    source_ip = "169.254.0.0"
    peer_ip = "169.254.0.1"
    table_id = "2"
  }
  bgp["desc2"] = {
    source_ip = "169.254.0.2"
    peer_ip = "169.254.0.3"
    table_id = "3"
  }
  }
  vars.os = "brocade"
}

/* Brocade BGP check */
apply Service "BGP peer - " for (bgp => config in host.vars.bgp.bgp) {
  import "generic-service"
  check_command = "check-bgp-brocade"
  vars.source = config.source_ip
  vars.peer = config.peer_ip
  vars.table = config.table_id
  assign where host.vars.bgp && host.vars.os == "brocade"
}

Unitary, each of these implementation works. The issue is that Icinga2 do not evaluate the assign where rule in the good order IMO because it throw an exception based on the facts that the apply Service rule dedicated to the Junos kind doesn't work on the Brocade kind, which is expected :

/etc/icinga2/conf.d/provisionning/services.conf(16): /* Junos BGP check */
/etc/icinga2/conf.d/provisionning/services.conf(17): apply Service "BGP peer - " for (description in host.vars.bgp) {
                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/etc/icinga2/conf.d/provisionning/services.conf(18):   import "generic-service"
/etc/icinga2/conf.d/provisionning/services.conf(19):   check_command = "check-junos-bgp-state"

        (0) Evaluating 'apply' rule (in /etc/icinga2/conf.d/provisionning/services.conf: 17:1-17:62)
        (1) Evaluating 'apply' rules for host 'host-brocade'

[2019-03-13 12:24:14 +0100] critical/config: Error: Array iterator requires value to be an array.

Icinga2 first evaluate the expression against any variable vars.bgp defecting the purpose of the assign where rule.

As a workaround I renamed vars.bgp to vars.bgp_b for the Brocade context. I'm not sure now of the behaviour of this assign where rule.

Expected Behavior

I suppose the apply Service rule with an assign where condition not matching a specific host should NOT evaluate the variables defined inside NON matching host, even if the vars names are the same.

Your Environment

Copyright (c) 2012-2019 Icinga GmbH (https://icinga.com/) License GPLv2+: GNU GPL version 2 or later http://gnu.org/licenses/gpl2.html This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

System information: Platform: Ubuntu Platform version: 16.04.5 LTS (Xenial Xerus) Kernel: Linux Kernel version: 4.4.0-138-generic Architecture: x86_64

Build information: Compiler: GNU 5.3.1 Build host: fd3f712856b4

Application information:

General paths: Config directory: /etc/icinga2 Data directory: /var/lib/icinga2 Log directory: /var/log/icinga2 Cache directory: /var/cache/icinga2 Spool directory: /var/spool/icinga2 Run directory: /run/icinga2

Old paths (deprecated): Installation root: /usr Sysconf directory: /etc Run directory (base): /run Local state directory: /var

Internal paths: Package data directory: /usr/share/icinga2 State path: /var/lib/icinga2/icinga2.state Modified attributes path: /var/lib/icinga2/modified-attributes.conf Objects path: /var/cache/icinga2/icinga2.debug Vars path: /var/cache/icinga2/icinga2.vars PID path: /run/icinga2/icinga2.pid

* Enabled features (`icinga2 feature list`):

Disabled features: compatlog debuglog elasticsearch gelf graphite influxdb opentsdb statusdata syslog Enabled features: api checker command ido-pgsql livestatus mainlog notification perfdata

* Config validation (`icinga2 daemon -C`):

[2019-03-13 13:17:27 +0100] information/cli: Icinga application loader (version: r2.10.3-1) [2019-03-13 13:17:27 +0100] information/cli: Loading configuration file(s). [2019-03-13 13:17:27 +0100] information/ConfigItem: Committing config item(s). [2019-03-13 13:17:27 +0100] information/ApiListener: My API identity: icinga2-monprod0.intercloud.fr [2019-03-13 13:17:28 +0100] warning/ApplyRule: Apply rule 'Uptime' (in /etc/icinga2/conf.d/provisionning/services.conf: 51:1-51:22) for type 'Service' does not match anywhere! [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 1494 Services. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 1 LivestatusListener. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 1 IcingaApplication. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 151 Hosts. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 1 FileLogger. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 4 NotificationCommands. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 1645 Notifications. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 1 NotificationComponent. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 9 HostGroups. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 1 ApiListener. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 1 PerfdataWriter. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 1 CheckerComponent. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 3 Zones. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 1 ExternalCommandListener. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 1 Endpoint. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 1 User. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 225 CheckCommands. [2019-03-13 13:17:28 +0100] information/ConfigItem: Instantiated 1 IdoPgsqlConnection. [2019-03-13 13:17:28 +0100] information/ScriptGlobal: Dumping variables to file '/var/cache/icinga2/icinga2.vars' [2019-03-13 13:17:28 +0100] information/cli: Finished validating the configuration file(s).

dnsmichi commented 5 years ago

That's not supported, the apply for expression definitely needs a unique name for providing the list being iterated. That is the first matching filter to actually attempt to generate objects - assign where expressions are filters evaluated at a later point.

Using the same variable name with different value types and operations is generally not best practice and can lead to unwanted errors - not only with for loops, but any sorts of expressions.

Refine your configuration and use dedicated and unique attribute names for 1) the array values 2) the dictionary values.

Cheers, Michael

Gnoale commented 5 years ago

Ok thanks for the quick answer.