1# Language Reference <a id="language-reference"></a>
2
3## Object Definition <a id="object-definition"></a>
4
5Icinga 2 features an object-based configuration format. You can define new
6objects using the `object` keyword:
7
8```
9object Host "host1.example.org" {
10  display_name = "host1"
11
12  address = "192.168.0.1"
13  address6 = "2001:db8:1234::42"
14}
15```
16
17In general you need to write each statement on a new line. Expressions started
18with `{`, `(` and `[` extend until the matching closing character and can be broken
19up into multiple lines.
20
21Alternatively you can write multiple statements on a single line by separating
22them with a semicolon:
23
24```
25object Host "host1.example.org" {
26  display_name = "host1"
27
28  address = "192.168.0.1"; address6 = "2001:db8:1234::42"
29}
30```
31
32Each object is uniquely identified by its type (`Host`) and name
33(`host1.example.org`). Some types have composite names, e.g. the
34`Service` type which uses the `host_name` attribute and the name
35you specified to generate its object name.
36
37Exclamation marks (!) are not permitted in object names.
38
39Objects can contain a comma-separated list of property
40declarations. Instead of commas semicolons may also be used.
41The following data types are available for property values:
42
43All objects have at least the following attributes:
44
45Attribute            | Description
46---------------------|-----------------------------
47name                 | The name of the object. This attribute can be modified in the object definition to override the name specified with the `object` directive.
48type                 | The type of the object.
49
50## Expressions <a id="expressions"></a>
51
52The following expressions can be used on the right-hand side of assignments.
53
54### Numeric Literals <a id="numeric-literals"></a>
55
56A floating-point number.
57
58Example:
59
60```
6127.3
62```
63
64### Duration Literals <a id="duration-literals"></a>
65
66Similar to floating-point numbers except for the fact that they support
67suffixes to help with specifying time durations.
68
69Example:
70
71```
722.5m
73```
74
75Supported suffixes include ms (milliseconds), s (seconds), m (minutes),
76h (hours) and d (days).
77
78Duration literals are converted to seconds by the config parser and
79are treated like numeric literals.
80
81### String Literals <a id="string-literals"></a>
82
83A string.
84
85Example:
86
87```
88"Hello World!"
89```
90
91#### String Literals Escape Sequences <a id="string-literals-escape-sequences"></a>
92
93Certain characters need to be escaped. The following escape sequences
94are supported:
95
96Character                 | Escape sequence
97--------------------------|------------------------------------
98"                         | \\"
99\\                        | \\\\
100&lt;TAB&gt;               | \\t
101&lt;CARRIAGE-RETURN&gt;   | \\r
102&lt;LINE-FEED&gt;         | \\n
103&lt;BEL&gt;               | \\b
104&lt;FORM-FEED&gt;         | \\f
105
106In addition to these pre-defined escape sequences you can specify
107arbitrary ASCII characters using the backslash character (\\) followed
108by an ASCII character in octal encoding.
109
110### Multi-line String Literals <a id="multiline-string-literals"></a>
111
112Strings spanning multiple lines can be specified by enclosing them in
113{{{ and }}}.
114
115Example:
116
117```
118{{{This
119is
120a multi-line
121string.}}}
122```
123
124Unlike in ordinary strings special characters do not have to be escaped
125in multi-line string literals.
126
127### Boolean Literals <a id="boolean-literals"></a>
128
129The keywords `true` and `false` are used to denote truth values.
130
131### Null Value <a id="null-value"></a>
132
133The `null` keyword can be used to specify an empty value.
134
135### Dictionary <a id="dictionary"></a>
136
137An unordered list of key-value pairs. Keys must be unique and are
138compared in a case-sensitive manner.
139
140Individual key-value pairs must either be comma-separated or on separate lines.
141The comma after the last key-value pair is optional.
142
143Example:
144
145```
146{
147  address = "192.168.0.1"
148  port = 443
149}
150```
151
152Identifiers may not contain certain characters (e.g. space) or start
153with certain characters (e.g. digits). If you want to use a dictionary
154key that is not a valid identifier, you can enclose the key in double
155quotes.
156
157### Array <a id="array"></a>
158
159An ordered list of values.
160
161Individual array elements must be comma-separated.
162The comma after the last element is optional.
163
164Example:
165
166```
167[ "hello", 42 ]
168```
169
170An array may simultaneously contain values of different types, such as
171strings and numbers.
172
173### Operators <a id="expression-operators"></a>
174
175The following operators are supported in expressions. The operators are sorted by descending precedence.
176
177Operator | Precedence | Examples (Result)                             | Description
178---------|------------|-----------------------------------------------|--------------------------------
179`()`       | 1          | (3 + 3) * 5                                   | Groups sub-expressions
180`()`       | 1          | Math.random()                                 | Calls a function
181`[]`       | 1          | a[3]                                          | Array subscript
182`.`       | 1          | a.b                                           | Element access
183`!`        | 2          | !"Hello" (false), !false (true)               | Logical negation of the operand
184`~`        | 2          | ~true (false)                                 | Bitwise negation of the operand
185`+`        | 2          | +3                                            | Unary plus
186`-`        | 2          | -3                                            | Unary minus
187`&`        | 2          | &var (reference to 'var')                     | Reference operator
188`*`        | 2          | *var                                          | Indirection operator
189`*`        | 3          | 5m * 10 (3000)                                | Multiplies two numbers
190`/`        | 3          | 5m / 5 (60)                                   | Divides two numbers
191`%`        | 3          | 17 % 12 (5)                                   | Remainder after division
192`+`        | 4          | 1 + 3 (4), "hello " + "world" ("hello world") | Adds two numbers; concatenates strings
193`-`        | 4          | 3 - 1 (2)                                     | Subtracts two numbers
194`<<`       | 5          | 4 << 8 (1024)                                 | Left shift
195`>>`       | 5          | 1024 >> 4 (64)                                | Right shift
196`<`        | 6         | 3 < 5 (true)                                  | Less than
197`>`        | 6         | 3 > 5 (false)                                 | Greater than
198`<=`       | 6         | 3 <= 3 (true)                                 | Less than or equal
199`>=`       | 6         | 3 >= 3 (true)                                 | Greater than or equal
200`in`       | 7          | "foo" in [ "foo", "bar" ] (true)              | Element contained in array
201`!in`      | 7          | "foo" !in [ "bar", "baz" ] (true)             | Element not contained in array
202`==`       | 8         | "hello" == "hello" (true), 3 == 5 (false)     | Equal to
203`!=`       | 8         | "hello" != "world" (true), 3 != 3 (false)     | Not equal to
204`&`        | 9          | 7 & 3 (3)                                     | Binary AND
205`^`        | 10          | 17 ^ 12 (29)                                  | Bitwise XOR
206<code>&#124;</code>    | 11          | 2 &#124; 3 (3)                                | Binary OR
207<code>&#124;&#124;</code>  | 12     | true &#124;&#124; false (true), 0 &#124;&#124; 7 (7)| Logical OR
208`&&`       | 13         | true && false (false), 3 && 7 (7), 0 && 7 (0) | Logical AND
209`=`        | 14         | a = 3                                         | Assignment
210`=>`       | 15         | x => x * x (function with arg x)              | Lambda, for loop
211`?`        | 16         | (2 * 3 > 5) ? 1 : 0 (1)                       | [Ternary operator](17-language-reference.md#conditional-statements-ternary)
212
213### References <a id="references"></a>
214
215A reference to a value can be obtained using the `&` operator. The `*` operator can be used
216to dereference a reference:
217
218```
219var value = "Hello!"
220var p = &value /* p refers to value */
221*p = "Hi!"
222log(value) // Prints "Hi!" because the variable was changed
223```
224
225### Namespaces <a id="namespaces"></a>
226
227Namespaces can be used to organize variables and functions. They are used to avoid name conflicts. The `namespace`
228keyword is used to create a new namespace:
229
230```
231namespace Utils {
232    function calculate() {
233        return 2 + 2
234    }
235}
236```
237
238The namespace is made available as a global variable which has the namespace's name (e.g. `Utils`):
239
240```
241Utils.calculate()
242```
243
244The `using` keyword can be used to make all attributes in a namespace available to a script without having to
245explicitly specify the namespace's name for each access:
246
247```
248using Utils
249calculate()
250```
251
252The `using` keyword only has an effect for the current file and only for code that follows the keyword:
253
254```
255calculate() // This will not work.
256using Utils
257```
258
259The following namespaces are automatically imported as if by using the `using` keyword:
260
261* System
262* System.Configuration
263* Types
264* Icinga
265
266### Function Calls <a id="function-calls"></a>
267
268Functions can be called using the `()` operator:
269
270```
271const MyGroups = [ "test1", "test" ]
272
273{
274  check_interval = len(MyGroups) * 1m
275}
276```
277
278A list of available functions is available in the [Library Reference](18-library-reference.md#library-reference) chapter.
279
280## Assignments <a id="dictionary-operators"></a>
281
282In addition to the `=` operator shown above a number of other operators
283to manipulate attributes are supported. Here's a list of all
284available operators (the outermost `{` `}` stand for a local variable scope):
285
286### Operator = <a id="operator-assignment"></a>
287
288Sets an attribute to the specified value.
289
290Example:
291
292```
293{
294  a = 5
295  a = 7
296}
297```
298
299In this example `a` has the value `7` after both instructions are executed.
300
301### Operator += <a id="operator-additive-assignment"></a>
302
303The += operator is a shortcut. The following expression:
304
305```
306{
307  a = [ "hello" ]
308  a += [ "world" ]
309}
310```
311
312is equivalent to:
313
314```
315{
316  a = [ "hello" ]
317  a = a + [ "world" ]
318}
319```
320
321### Operator -= <a id="operator-substractive-assignment"></a>
322
323The -= operator is a shortcut. The following expression:
324
325```
326{
327  a = 10
328  a -= 5
329}
330```
331
332is equivalent to:
333
334```
335{
336  a = 10
337  a = a - 5
338}
339```
340
341### Operator \*= <a id="operator-multiply-assignment"></a>
342
343The *= operator is a shortcut. The following expression:
344
345```
346{
347  a = 60
348  a *= 5
349}
350```
351
352is equivalent to:
353
354```
355{
356  a = 60
357  a = a * 5
358}
359```
360
361### Operator /= <a id="operator-dividing-assignment"></a>
362
363The /= operator is a shortcut. The following expression:
364
365```
366{
367  a = 300
368  a /= 5
369}
370```
371
372is equivalent to:
373
374```
375{
376  a = 300
377  a = a / 5
378}
379```
380
381## Indexer <a id="indexer"></a>
382
383The indexer syntax provides a convenient way to set dictionary elements.
384
385Example:
386
387```
388{
389  hello.key = "world"
390}
391```
392
393Example (alternative syntax):
394
395```
396{
397  hello["key"] = "world"
398}
399```
400
401This is equivalent to writing:
402
403```
404{
405  hello += {
406    key = "world"
407  }
408}
409```
410
411If the `hello` attribute does not already have a value, it is automatically initialized to an empty dictionary.
412
413## Template Imports <a id="template-imports"></a>
414
415Objects can import attributes from other objects.
416
417Example:
418
419```
420template Host "default-host" {
421  vars.colour = "red"
422}
423
424template Host "test-host" {
425  import "default-host"
426
427  vars.colour = "blue"
428}
429
430object Host "localhost" {
431  import "test-host"
432
433  address = "127.0.0.1"
434  address6 = "::1"
435}
436```
437
438The `default-host` and `test-host` objects are marked as templates
439using the `template` keyword. Unlike ordinary objects templates are not
440instantiated at run-time. Parent objects do not necessarily have to be
441templates, however in general they are.
442
443The `vars` dictionary for the `localhost` object contains all three
444custom variables and the custom variable `colour` has the value `"blue"`.
445
446Parent objects are resolved in the order they're specified using the
447`import` keyword.
448
449Default templates which are automatically imported into all object definitions
450can be specified using the `default` keyword:
451
452```
453template CheckCommand "plugin-check-command" default {
454  // ...
455}
456```
457
458Default templates are imported before any other user-specified statement in an
459object definition is evaluated.
460
461If there are multiple default templates the order in which they are imported
462is unspecified.
463
464## Constants <a id="constants"></a>
465
466Global constants can be set using the `const` keyword:
467
468```
469const VarName = "some value"
470```
471
472Once defined a constant can be accessed from any file. Constants cannot be changed
473once they are set.
474
475> **Tip**
476>
477> Best practice is to manage constants in the [constants.conf](04-configuration.md#constants-conf) file.
478
479### Icinga 2 Specific Constants <a id="icinga-constants"></a>
480
481Icinga 2 provides a number of special global constants. These include directory paths, global configuration
482and runtime parameters for the application version and (build) platform.
483
484#### Directory Path Constants <a id="icinga-constants-director-path"></a>
485
486Constant            | Description
487--------------------|-------------------
488ConfigDir           |**Read-only.** Main configuration directory. Usually set to `/etc/icinga2`.
489DataDir             |**Read-only.** Runtime data for the Icinga daemon. Usually set to `/var/lib/icinga2`.
490LogDir              |**Read-only.** Logfiles from the daemon. Usually set to `/var/log/icinga2`.
491CacheDir            |**Read-only.** Cached status information of the daemon. Usually set to `/var/cache/icinga2`.
492SpoolDir            |**Read-only.** Spool directory for certain data outputs. Usually set to `/var/spool/icinga2`.
493InitRunDir          |**Read-only.** Directory for PID files and sockets in daemon mode. Usually set to `/run/icinga2`.
494ZonesDir            |**Read-only.** Contains the path of the zones.d directory. Defaults to `ConfigDir + "/zones.d"`.
495
496#### Global Configuration Constants <a id="icinga-constants-global-config"></a>
497
498Constant            | Description
499--------------------|-------------------
500Vars                |**Read-write.** Contains a dictionary with global custom variables. Not set by default.
501NodeName            |**Read-write.** Contains the cluster node name. Set to the local hostname by default.
502ReloadTimeout       |**Read-write.** Defines the reload timeout for child processes. Defaults to `300s`.
503Environment         |**Read-write.** The name of the Icinga environment. Included in the SNI host name for outbound connections. Not set by default.
504RunAsUser           |**Read-write.** Defines the user the Icinga 2 daemon is running as. Set in the Icinga 2 sysconfig.
505RunAsGroup          |**Read-write.** Defines the group the Icinga 2 daemon is running as. Set in the Icinga 2 sysconfig.
506MaxConcurrentChecks |**Read-write.** The number of max checks run simultaneously. Defaults to `512`.
507ApiBindHost         |**Read-write.** Overrides the default value for the ApiListener `bind_host` attribute. Defaults to `::` if IPv6 is supported by the operating system and to `0.0.0.0` otherwise.
508ApiBindPort         |**Read-write.** Overrides the default value for the ApiListener `bind_port` attribute. Not set by default.
509
510#### Application Runtime Constants <a id="icinga-constants-application-runtime"></a>
511
512Constant            | Description
513--------------------|-------------------
514PlatformName        |**Read-only.** The name of the operating system, e.g. `Ubuntu`.
515PlatformVersion     |**Read-only.** The version of the operating system, e.g. `14.04.3 LTS`.
516PlatformKernel      |**Read-only.** The name of the operating system kernel, e.g. `Linux`.
517PlatformKernelVersion|**Read-only.** The version of the operating system kernel, e.g. `3.13.0-63-generic`.
518BuildCompilerName   |**Read-only.** The name of the compiler Icinga was built with, e.g. `Clang`.
519BuildCompilerVersion|**Read-only.** The version of the compiler Icinga was built with, e.g. `7.3.0.7030031`.
520BuildHostName       |**Read-only.** The name of the host Icinga was built on, e.g. `acheron`.
521ApplicationVersion  |**Read-only.** The application version, e.g. `2.9.0`.
522
523#### Additional Constants <a id="icinga-constants-additional"></a>
524
525Writable constants can be specified on the CLI using the `--define/-D` parameter.
526
527> **Note for v2.10+**
528>
529> Default paths which include `/etc` and `/var` as base directory continue to work
530> based on the `SysconfDir` and `LocalStateDir` constants respectively.
531
532In addition to that, the constants below are used to define specific file paths. You should never need
533to change them, as they are pre-compiled based on the constants above.
534
535Variable            |Description
536--------------------|-------------------
537StatePath           |**Read-write.** Contains the path of the Icinga 2 state file. Defaults to `DataDir + "/icinga2.state"`.
538ObjectsPath         |**Read-write.** Contains the path of the Icinga 2 objects file. Defaults to `CacheDir + "/icinga2.debug"`.
539PidPath             |**Read-write.** Contains the path of the Icinga 2 PID file. Defaults to `InitRunDir + "/icinga2.pid"`.
540PkgDataDir          |**Read-only.** Contains the path of the package data directory. Defaults to `PrefixDir + "/share/icinga2"`.
541
542The constants below have been used until Icinga v2.10, and are still intact. You don't need them
543for future builds and configuration based on the newly available constants above.
544
545Variable            |Description
546--------------------|-------------------
547PrefixDir           |**Read-only.** Contains the installation prefix that was specified with `cmake -DCMAKE_INSTALL_PREFIX`. `Defaults to "/usr/local"`.
548SysconfDir          |**Read-only.** Contains the path of the sysconf directory. Defaults to `PrefixDir + "/etc"`.
549LocalStateDir       |**Read-only.** Contains the path of the local state directory. Defaults to `PrefixDir + "/var"`.
550RunDir              |**Read-only.** Contains the path of the run directory. Defaults to `LocalStateDir + "/run"`.
551
552#### Advanced Constants and Variables <a id="icinga-constants-advanced"></a>
553
554Advanced runtime constants. Please only use them if advised by support or developers.
555
556Variable                   | Description
557---------------------------|-------------------
558EventEngine                |**Read-write.** The name of the socket event engine, can be `poll` or `epoll`. The epoll interface is only supported on Linux.
559AttachDebugger             |**Read-write.** Whether to attach a debugger when Icinga 2 crashes. Defaults to `false`.
560
561Advanced sysconfig environment variables, defined in `/etc/sysconfig/icinga2` (RHEL/SLES) or `/etc/default/icinga2` (Debian/Ubuntu).
562
563Variable                   | Description
564---------------------------|-------------------
565ICINGA2\_RLIMIT\_FILES     |**Read-write.** Defines the resource limit for `RLIMIT_NOFILE` that should be set at start-up. Value cannot be set lower than the default `16 * 1024`. 0 disables the setting. Set in Icinga 2 sysconfig.
566ICINGA2\_RLIMIT\_PROCESSES |**Read-write.** Defines the resource limit for `RLIMIT_NPROC` that should be set at start-up. Value cannot be set lower than the default `16 * 1024`. 0 disables the setting. Set in Icinga 2 sysconfig.
567ICINGA2\_RLIMIT\_STACK     |**Read-write.** Defines the resource limit for `RLIMIT_STACK` that should be set at start-up. Value cannot be set lower than the default `256 * 1024`. 0 disables the setting. Set in Icinga 2 sysconfig.
568
569#### Debug Constants and Variables <a id="icinga-constants-debug"></a>
570
571These constants are only available in debug builds for developers and help with tracing messages and attaching to debuggers.
572
573Variable                   | Description
574---------------------------|-------------------
575Internal.DebugJsonRpc      | **Read-write.** Setting this to `1` prints the raw JSON-RPC message to STDOUT.
576Internal.DebugWorkerDelay  | **Read-write.** Delays the main worker process by X seconds after forked from the umbrella process. This helps with attaching LLDB which cannot follow child forks like GDB.
577
578Example:
579
580```
581$ icinga2 daemon -DInternal.DebugWorkerDelay=120
582Closed FD 6 which we inherited from our parent process.
583[2020-01-29 12:22:33 +0100] information/cli: Icinga application loader (version: v2.11.0-477-gfe8701d77; debug)
584[2020-01-29 12:22:33 +0100] information/RunWorker: DEBUG: Current PID: 85253. Sleeping for 120 seconds to allow lldb/gdb -p <PID> attachment.
585
586$ lldb -p 85253
587(lldb) b icinga::Checkable::ProcessCheckResult
588(lldb) c
589```
590
591
592## Apply <a id="apply"></a>
593
594The `apply` keyword can be used to create new objects which are associated with
595another group of objects.
596
597```
598apply Service "ping" to Host {
599  import "generic-service"
600
601  check_command = "ping4"
602
603  assign where host.name == "localhost"
604}
605```
606
607In this example the `assign where` condition is a boolean expression which is
608evaluated for all objects of type `Host` and a new service with name "ping"
609is created for each matching host. [Expression operators](17-language-reference.md#expression-operators)
610may be used in `assign where` conditions.
611
612The `to` keyword and the target type may be omitted if there is only one target
613type, e.g. for the `Service` type.
614
615Depending on the object type used in the `apply` expression additional local
616variables may be available for use in the `where` condition:
617
618Source Type       | Target Type | Variables
619------------------|-------------|--------------
620Service           | Host        | host
621Dependency        | Host        | host
622Dependency        | Service     | host, service
623Notification      | Host        | host
624Notification      | Service     | host, service
625ScheduledDowntime | Host        | host
626ScheduledDowntime | Service     | host, service
627
628Any valid config attribute can be accessed using the `host` and `service`
629variables. For example, `host.address` would return the value of the host's
630"address" attribute -- or null if that attribute isn't set.
631
632More usage examples are documented in the [monitoring basics](03-monitoring-basics.md#using-apply-expressions)
633chapter.
634
635## Apply For <a id="apply-for"></a>
636
637[Apply](17-language-reference.md#apply) rules can be extended with the
638[for loop](17-language-reference.md#for-loops) keyword.
639
640```
641apply Service "prefix-" for (key => value in host.vars.dictionary) to Host {
642  import "generic-service"
643
644  check_command = "ping4"
645  vars.host_value = value
646}
647```
648
649Any valid config attribute can be accessed using the `host` and `service`
650variables. The attribute must be of the Array or Dictionary type. In this example
651`host.vars.dictionary` is of the Dictionary type which needs a key-value-pair
652as iterator.
653
654In this example all generated service object names consist of `prefix-` and
655the value of the `key` iterator. The prefix string can be omitted if not required.
656
657The `key` and `value` variables can be used for object attribute assignment, e.g. for
658setting the `check_command` attribute or custom variables as command parameters.
659
660`apply for` rules are first evaluated against all objects matching the `for loop` list
661and afterwards the `assign where` and `ignore where` conditions are evaluated.
662
663It is not necessary to check attributes referenced in the `for loop` expression
664for their existance using an additional `assign where` condition.
665
666More usage examples are documented in the [monitoring basics](03-monitoring-basics.md#using-apply-for)
667chapter.
668
669## Group Assign <a id="group-assign"></a>
670
671Group objects can be assigned to specific member objects using the `assign where`
672and `ignore where` conditions.
673
674```
675object HostGroup "linux-servers" {
676  display_name = "Linux Servers"
677
678  assign where host.vars.os == "Linux"
679}
680```
681
682In this example the `assign where` condition is a boolean expression which is evaluated
683for all objects of the type `Host`. Each matching host is added as member to the host group
684with the name "linux-servers". Membership exclusion can be controlled using the `ignore where`
685condition. [Expression operators](17-language-reference.md#expression-operators) may be used in `assign where` and
686`ignore where` conditions.
687
688Source Type       | Variables
689------------------|--------------
690HostGroup         | host
691ServiceGroup      | host, service
692UserGroup         | user
693
694
695## Boolean Values <a id="boolean-values"></a>
696
697The `assign where`, `ignore where`, `if` and `while`  statements, the `!` operator as
698well as the `bool()` function convert their arguments to a boolean value based on the
699following rules:
700
701Description          | Example Value     | Boolean Value
702---------------------|-------------------|--------------
703Empty value          | null              | false
704Zero                 | 0                 | false
705Non-zero integer     | -23945            | true
706Empty string         | ""                | false
707Non-empty string     | "Hello"           | true
708Empty array          | []                | false
709Non-empty array      | [ "Hello" ]       | true
710Empty dictionary     | {}                | false
711Non-empty dictionary | { key = "value" } | true
712
713For a list of supported expression operators for `assign where` and `ignore where`
714statements, see [expression operators](17-language-reference.md#expression-operators).
715
716## Comments <a id="comments"></a>
717
718The Icinga 2 configuration format supports C/C++-style and shell-style comments.
719
720Example:
721
722```
723/*
724 This is a comment.
725 */
726object Host "localhost" {
727  check_interval = 30 // this is also a comment.
728  retry_interval = 15 # yet another comment
729}
730```
731
732## Includes <a id="includes"></a>
733
734Other configuration files can be included using the `include` directive.
735Paths must be relative to the configuration file that contains the
736`include` directive.
737
738Example:
739
740```
741include "some/other/file.conf"
742include "conf.d/*.conf"
743```
744
745Wildcard includes are not recursive.
746
747Icinga also supports include search paths similar to how they work in a
748C/C++ compiler:
749
750```
751include <itl>
752```
753
754Note the use of angle brackets instead of double quotes. This causes the
755config compiler to search the include search paths for the specified
756file. By default $PREFIX/share/icinga2/include is included in the list of search
757paths. Additional include search paths can be added using
758[command-line options](11-cli-commands.md#config-include-path).
759
760Wildcards are not permitted when using angle brackets.
761
762## Recursive Includes <a id="recursive-includes"></a>
763
764The `include_recursive` directive can be used to recursively include all
765files in a directory which match a certain pattern.
766
767Example:
768
769```
770include_recursive "conf.d", "*.conf"
771include_recursive "templates"
772```
773
774The first parameter specifies the directory from which files should be
775recursively included.
776
777The file names need to match the pattern given in the second parameter.
778When no pattern is specified the default pattern "*.conf" is used.
779
780## Zone Includes <a id="zone-includes"></a>
781
782> **Note**
783>
784> This is an internal functionality consumed by Icinga itself.
785>
786> The preferred way for users managing configuration files in
787> zones is to use the [cluster config sync](06-distributed-monitoring.md#distributed-monitoring-top-down-config-sync)
788> or [REST API config packages](12-icinga2-api.md#icinga2-api-config-management).
789
790The `include_zones` recursively includes all subdirectories for the
791given path.
792
793In addition to that it sets the `zone` attribute for all objects created
794in these subdirectories to the name of the subdirectory.
795
796Example:
797
798```
799include_zones "etc", "zones.d", "*.conf"
800include_zones "puppet", "puppet-zones"
801```
802
803The first parameter specifies a tag name for this directive. Each `include_zones`
804invocation should use a unique tag name. When copying the zones' configuration
805files Icinga uses the tag name as the name for the destination directory in
806`/var/lib/icinga2/api/config`.
807
808The second parameter specifies the directory which contains the subdirectories.
809
810The file names need to match the pattern given in the third parameter.
811When no pattern is specified the default pattern "*.conf" is used.
812
813## Library directive <a id="library"></a>
814
815The `library` directive was used to manually load additional
816libraries. Starting with version 2.9 it is no longer necessary to explicitly load
817libraries and this directive has no effect.
818
819## Functions <a id="functions"></a>
820
821Functions can be defined using the `function` keyword.
822
823Example:
824
825```
826function multiply(a, b) {
827  return a * b
828}
829```
830
831When encountering the `return` keyword further execution of the function is terminated and
832the specified value is supplied to the caller of the function:
833
834```
835log(multiply(3, 5))
836```
837
838In this example the `multiply` function we declared earlier is invoked with two arguments (3 and 5).
839The function computes the product of those arguments and makes the result available to the
840function's caller.
841
842When no value is supplied for the `return` statement the function returns `null`.
843
844Functions which do not have a `return` statement have their return value set to the value of the
845last expression which was performed by the function. For example, we could have also written our
846`multiply` function like this:
847
848```
849function multiply(a, b) {
850  a * b
851}
852```
853
854Anonymous functions can be created by omitting the name in the function definition. The
855resulting function object can be used like any other value:
856
857```
858var fn = function() { 3 }
859
860fn() /* Returns 3 */
861```
862
863## Lambda Expressions <a id="lambdas"></a>
864
865Functions can also be declared using the alternative lambda syntax.
866
867Example:
868
869```
870f = (x) => x * x
871```
872
873Multiple statements can be used by putting the function body into braces:
874
875```
876f = (x) => {
877  log("Lambda called")
878  x * x
879}
880```
881
882Just like with ordinary functions the return value is the value of the last statement.
883
884For lambdas which take exactly one argument the braces around the arguments can be omitted:
885
886```
887f = x => x * x
888```
889
890### Lambda Expressions with Closures <a id="lambdas-closures"></a>
891
892Lambda expressions which take a given number of arguments may need additional
893variable values from the outer scope. When the lambda expression does not allow
894to change the interface, [closures](17-language-reference.md#closures) come into play.
895
896```
897var y
898
899f = ((x) use(y) => x == y)
900```
901
902Note that the braces around arguments are always required when using closures.
903
904A more concrete example:
905
906Within the DSL, you want to [filter](18-library-reference.md#array-filter) an array of HostGroup objects by their name.
907The filter function takes one argument being a function callback which either returns
908`true` or `false`. Matching items are collected into the result set.
909
910```
911get_objects(HostGroup).filter((hg) => hg.name == "linux-servers")
912```
913
914Instead of hardcoding the matching hostgroup name into the lambda scope, you want
915to control the value from the outside configuration values, e.g. in a custom variable
916or global constant.
917
918```
919var hg_filter_name = "linux-servers"
920
921get_objects(HostGroup).filter((hg) use(hg_filter_name) => hg.name == hg_filter_name)
922```
923
924You can also use this example vice versa and extract host object matching a specific
925host group name.
926
927```
928var hg_filter_name = "linux-servers"
929
930get_objects(Host).filter((h) use (hg_search_name) => hg_search_name in h.groups).map(h => h.name)
931```
932
933Note that this example makes use of the [map](18-library-reference.md#array-map) method for the Array type which
934extracts the host name attribute from the full object into a new array.
935
936## Abbreviated Lambda Syntax <a id="nullary-lambdas"></a>
937
938Lambdas which take no arguments can also be written using the abbreviated lambda syntax.
939
940Example:
941
942```
943f = {{ 3 }}
944```
945
946This creates a new function which returns the value 3.
947
948## Variable Scopes <a id="variable-scopes"></a>
949
950When setting a variable Icinga checks the following scopes in this order whether the variable
951already exists there:
952
953* Local Scope
954* `this` Scope
955* Global Scope
956
957The local scope contains variables which only exist during the invocation of the current function,
958object or apply statement. Local variables can be declared using the `var` keyword:
959
960```
961function multiply(a, b) {
962  var temp = a * b
963  return temp
964}
965```
966
967Each time the `multiply` function is invoked a new `temp` variable is used which is in no way
968related to previous invocations of the function.
969
970When setting a variable which has not previously been declared as local using the `var` keyword
971the `this` scope is used.
972
973The `this` scope refers to the current object which the function or object/apply statement
974operates on.
975
976```
977object Host "localhost" {
978  check_interval = 5m
979}
980```
981
982In this example the `this` scope refers to the "localhost" object. The `check_interval` attribute
983is set for this particular host.
984
985You can explicitly access the `this` scope using the `this` keyword:
986
987```
988object Host "localhost" {
989  var check_interval = 5m
990
991  /* This explicitly specifies that the attribute should be set
992   * for the host, if we had omitted `this.` the (poorly named)
993   * local variable `check_interval` would have been modified instead.
994   */
995  this.check_interval = 1m
996}
997```
998Similarly the keywords `locals` and `globals` are available to access the local and global scope.
999
1000Functions also have a `this` scope. However unlike for object/apply statements the `this` scope for
1001a function is set to whichever object was used to invoke the function. Here's an example:
1002
1003```
1004 hm = {
1005   h_word = null
1006
1007   function init(word) {
1008     h_word = word
1009   }
1010 }
1011
1012 /* Let's invoke the init() function */
1013 hm.init("hello")
1014```
1015
1016We're using `hm.init` to invoke the function which causes the value of `hm` to become the `this`
1017scope for this function call.
1018
1019## Closures <a id="closures"></a>
1020
1021By default `function`s, `object`s and `apply` rules do not have access to variables declared
1022outside of their scope (except for global variables).
1023
1024In order to access variables which are defined in the outer scope the `use` keyword can be used:
1025
1026```
1027function MakeHelloFunction(name) {
1028  return function() use(name) {
1029    log("Hello, " + name)
1030  }
1031}
1032```
1033
1034In this case a new variable `name` is created inside the inner function's scope which has the
1035value of the `name` function argument.
1036
1037Alternatively a different value for the inner variable can be specified:
1038
1039```
1040function MakeHelloFunction(name) {
1041  return function() use (greeting = "Hello, " + name) {
1042    log(greeting)
1043  }
1044}
1045```
1046
1047## Conditional Statements <a id="conditional-statements"></a>
1048
1049### Conditional Statements: if/else <a id="conditional-statements-if-else"></a>
1050
1051Sometimes it can be desirable to only evaluate statements when certain conditions are met. The if/else
1052construct can be used to accomplish this.
1053
1054Example:
1055
1056```
1057a = 3
1058
1059if (a < 5) {
1060  a *= 7
1061} else if (a > 10) {
1062  a *= 5
1063} else {
1064  a *= 2
1065}
1066```
1067
1068An if/else construct can also be used in place of any other value. The value of an if/else statement
1069is the value of the last statement which was evaluated for the branch which was taken:
1070
1071```
1072a = if (true) {
1073  log("Taking the 'true' branch")
1074  7 * 3
1075} else {
1076  log("Taking the 'false' branch")
1077  9
1078}
1079```
1080
1081This example prints the log message "Taking the 'true' branch" and the `a` variable is set to 21 (7 * 3).
1082
1083The value of an if/else construct is null if the condition evaluates to false and no else branch is given.
1084
1085### Conditional Statements: Ternary Operator <a id="conditional-statements-ternary"></a>
1086
1087Instead of if/else condition chains, you can also use the ternary operator `?`
1088with assignments. Values are separated with a colon `:` character.
1089
1090```
1091cond ? cond_val_true : cond_val_false
1092```
1093
1094Whether the first condition matches, the first value is returned, if not, the else and second
1095branch value is returned.
1096
1097The following example evaluates a condition and either assigns `1` or `0`
1098to the local variable.
1099
1100```
1101<1> => var x = (2 * 3 > 5) ? 1 : 0
1102null
1103<2> => x
11041.000000
1105<3> => var x = (2 * 3 > 7) ? 1 : 0
1106null
1107<4> => x
11080.000000
1109```
1110
1111Additional examples with advanced condition chaining:
1112
1113```
1114<1> => 1 ? 2 : 3 ? 4 : 5 ? 6 : 7
11152.000000
1116<2> => 0 ? 2 : 3 ? 4 : 5 ? 6 : 7
11174.000000
1118<3> => 0 ? 2 : 0 ? 4 : 5 ? 6 : 7
11196.000000
1120<4> => 0 ? 2 : 0 ? 4 : 0 ? 6 : 7
11217.000000
1122<5> => 1 + 0 ? 2 : 3 + 4
11232.000000
1124<6> => 0 + 0 ? 2 : 3 + 4
11257.000000
1126<7> => (()=>{ return 1 ? 2 : 3 })()
11272.000000
1128<8> => var x = 1 ? 2 : 3
1129null
1130<9> => x
11312.000000
1132```
1133
1134
1135## While Loops <a id="while-loops"></a>
1136
1137The `while` statement checks a condition and executes the loop body when the condition evaluates to `true`.
1138This is repeated until the condition is no longer true.
1139
1140Example:
1141
1142```
1143var num = 5
1144
1145while (num > 5) {
1146    log("Test")
1147    num -= 1
1148}
1149```
1150
1151The `continue` and `break` keywords can be used to control how the loop is executed: The `continue` keyword
1152skips over the remaining expressions for the loop body and begins the next loop evaluation. The `break` keyword
1153breaks out of the loop.
1154
1155## For Loops <a id="for-loops"></a>
1156
1157The `for` statement can be used to iterate over arrays and dictionaries.
1158
1159Example:
1160
1161```
1162var list = [ "a", "b", "c" ]
1163
1164for (var item in list) {
1165  log("Item: " + item)
1166}
1167```
1168
1169The loop body is evaluated once for each item in the array. The variable `item` is declared as a local
1170variable just as if the `var` keyword had been used.
1171
1172Iterating over dictionaries can be accomplished in a similar manner:
1173
1174```
1175var dict = { a = 3, b = 7 }
1176
1177for (var key => var value in dict) {
1178  log("Key: " + key + ", Value: " + value)
1179}
1180```
1181
1182The `continue` and `break` keywords can be used to control how the loop is executed: The `continue` keyword
1183skips over the remaining expressions for the loop body and begins the next loop evaluation. The `break` keyword
1184breaks out of the loop.
1185
1186The `var` keyword is optional when declaring variables in the loop's header. Variables declared without the `var`
1187keyword are nonetheless local to the function.
1188
1189## Constructors <a id="constructor"></a>
1190
1191In order to create a new value of a specific type constructor calls may be used.
1192
1193Example:
1194
1195```
1196var pd = PerfdataValue()
1197pd.label = "test"
1198pd.value = 10
1199```
1200
1201You can also try to convert an existing value to another type by specifying it as an argument for the constructor call.
1202
1203Example:
1204
1205```
1206var s = String(3) /* Sets s to "3". */
1207```
1208
1209## Throwing Exceptions <a id="throw"></a>
1210
1211Built-in commands may throw exceptions to signal errors such as invalid arguments. User scripts can throw exceptions
1212using the `throw` keyword.
1213
1214Example:
1215
1216```
1217throw "An error occurred."
1218```
1219
1220## Handling Exceptions <a id="try-except"></a>
1221
1222Exceptions can be handled using the `try` and `except` keywords. When an exception occurs while executing code in the
1223`try` clause no further statements in the `try` clause are evaluated and the `except` clause is executed instead.
1224
1225Example:
1226
1227```
1228try {
1229    throw "Test"
1230
1231    log("This statement won't get executed.")
1232} except {
1233    log("An error occurred in the try clause.")
1234}
1235```
1236
1237## Breakpoints <a id="breakpoints"></a>
1238
1239The `debugger` keyword can be used to insert a breakpoint. It may be used at any place where an assignment would also be a valid expression.
1240
1241By default breakpoints have no effect unless Icinga is started with the `--script-debugger` command-line option. When the script debugger is enabled Icinga stops execution of the script when it encounters a breakpoint and spawns a console which lets the user inspect the current state of the execution environment.
1242
1243## Types <a id="types"></a>
1244
1245All values have a static type. The `typeof` function can be used to determine the type of a value:
1246
1247```
1248typeof(3) /* Returns an object which represents the type for numbers */
1249```
1250
1251The following built-in types are available:
1252
1253Type       | Examples          | Description
1254-----------|-------------------|------------------------
1255Number     | 3.7               | A numerical value.
1256Boolean    | true, false       | A boolean value.
1257String     | "hello"           | A string.
1258Array      | [ "a", "b" ]      | An array.
1259Dictionary | { a = 3 }         | A dictionary.
1260
1261Depending on which libraries are loaded additional types may become available. The `icinga`
1262library implements a whole bunch of other [object types](09-object-types.md#object-types),
1263e.g. Host, Service, CheckCommand, etc.
1264
1265Each type has an associated type object which describes the type's semantics. These
1266type objects are made available using global variables which match the type's name:
1267
1268```
1269/* This logs 'true' */
1270log(typeof(3) == Number)
1271```
1272
1273The type object's `prototype` property can be used to find out which methods a certain type
1274supports:
1275
1276```
1277/* This returns: ["contains","find","len","lower","replace","reverse","split","substr","to_string","trim","upper"] */
1278keys(String.prototype)
1279```
1280
1281Additional documentation on type methods is available in the
1282[library reference](18-library-reference.md#library-reference).
1283
1284## Location Information <a id="location-information"></a>
1285
1286The location of the currently executing script can be obtained using the
1287`current_filename` and `current_line` keywords.
1288
1289Example:
1290
1291```
1292log("Hello from '" + current_filename + "' in line " + current_line)
1293```
1294
1295## Reserved Keywords <a id="reserved-keywords"></a>
1296
1297These keywords are reserved and must not be used as constants or custom variables.
1298
1299```
1300object
1301template
1302include
1303include_recursive
1304include_zones
1305library
1306null
1307true
1308false
1309const
1310var
1311this
1312globals
1313locals
1314use
1315default
1316ignore_on_error
1317current_filename
1318current_line
1319apply
1320to
1321where
1322import
1323assign
1324ignore
1325function
1326return
1327break
1328continue
1329for
1330if
1331else
1332while
1333throw
1334try
1335except
1336in
1337using
1338namespace
1339```
1340You can escape reserved keywords using the `@` character. The following example
1341tries to set `vars.include` which references a reserved keyword and generates
1342an error:
1343
1344```
1345[2014-09-15 17:24:00 +0200] critical/config: Location:
1346/etc/icinga2/conf.d/hosts/localhost.conf(13):   vars.sla = "24x7"
1347/etc/icinga2/conf.d/hosts/localhost.conf(14):
1348/etc/icinga2/conf.d/hosts/localhost.conf(15):   vars.include = "some cmdb export field"
1349                                                     ^^^^^^^
1350/etc/icinga2/conf.d/hosts/localhost.conf(16): }
1351/etc/icinga2/conf.d/hosts/localhost.conf(17):
1352
1353Config error: in /etc/icinga2/conf.d/hosts/localhost.conf: 15:8-15:14: syntax error, unexpected include (T_INCLUDE), expecting T_IDENTIFIER
1354[2014-09-15 17:24:00 +0200] critical/config: 1 errors, 0 warnings.
1355```
1356
1357You can escape the `include` keyword by prefixing it with an additional `@` character:
1358
1359```
1360object Host "localhost" {
1361  import "generic-host"
1362
1363  address = "127.0.0.1"
1364  address6 = "::1"
1365
1366  vars.os = "Linux"
1367  vars.sla = "24x7"
1368
1369  vars.@include = "some cmdb export field"
1370}
1371```
1372