]> granicus.if.org Git - icinga2/commitdiff
Support new-lines in addition to commas to separate commands.
authorGunnar Beutner <gunnar@beutner.name>
Mon, 31 Mar 2014 16:38:15 +0000 (18:38 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Tue, 1 Apr 2014 07:45:57 +0000 (09:45 +0200)
Fixes #5901

27 files changed:
doc/2.1-setting-up-icinga-2.md
doc/3.01-hosts-and-services.md
doc/3.02-commands.md
doc/3.03-macros.md
doc/3.04-notifications.md
doc/3.05-using-templates.md
doc/3.06-groups.md
doc/3.07-time-periods.md
doc/3.11-performance-data.md
doc/3.15-monitoring-remote-clients.md
doc/4.1-configuration-syntax.md
doc/4.3-object-types.md
doc/6.01-downtimes.md
doc/6.04-cluster.md
doc/6.05-domains.md
doc/6.06-dependencies.md
doc/8-differences-between-icinga-1x-and-2.md
etc/icinga2/conf.d/downtimes.conf
etc/icinga2/conf.d/generic-host.conf
etc/icinga2/conf.d/generic-service.conf
etc/icinga2/conf.d/localhost.conf
etc/icinga2/conf.d/notifications.conf
etc/icinga2/conf.d/timeperiods.conf
etc/icinga2/conf.d/users.conf
etc/icinga2/icinga2.conf
lib/config/config_lexer.ll
lib/config/config_parser.yy

index 1742bc23417ea4978decd50cb2ffc12af820f6be..68b557703303dd50ac98709f63c15a5d24a50698 100644 (file)
@@ -107,9 +107,9 @@ the features which have been enabled with `icinga2-enable-feature`. See
     /**
      * Although in theory you could define all your objects in this file
      * the preferred way is to create separate directories and files in the conf.d
-     * directory.
+     * directory. Each of these files must have the file extension ".conf".
      */
-    include_recursive "conf.d" "*.conf"
+    include_recursive "conf.d"
 
 You can put your own configuration files in the `conf.d` directory. This
 directive makes sure that all of your own configuration files are included.
@@ -136,9 +136,9 @@ The `conf.d/localhost.conf` file contains our first host definition:
      * files in this directory are included.
      */
     object Host "localhost" {
-      import "linux-server",
+      import "linux-server"
 
-      macros.address = "127.0.0.1",
+      macros.address = "127.0.0.1"
       macros.address6 = "::1"
     }
 
@@ -152,63 +152,63 @@ services which belong to this host. Most of the templates in the Icinga Template
 Library require an `address` macro.
 
     apply Service "icinga" {
-      import "generic-service",
+      import "generic-service"
 
-      check_command = "icinga",
+      check_command = "icinga"
 
       assign where host.name == "localhost"
     }
 
     apply Service "http" {
-      import "generic-service",
+      import "generic-service"
 
-      check_command = "http_ip",
+      check_command = "http_ip"
 
       assign where host.name == "localhost"
     }
 
     apply Service "ssh" {
-      import "generic-service",
+      import "generic-service"
 
-      check_command = "ssh",
+      check_command = "ssh"
 
       assign where host.name == "localhost"
     }
 
     apply Service "load" {
-      import "generic-service",
+      import "generic-service"
 
-      check_command = "load",
+      check_command = "load"
 
       assign where host.name == "localhost"
     }
 
     apply ScheduledDowntime "backup-downtime" {
-      import "backup-downtime",
+      import "backup-downtime"
 
       assign where service.host == "localhost" && service.short_name == "load"
     }
 
     apply Service "processes" {
-      import "generic-service",
+      import "generic-service"
 
-      check_command = "processes",
+      check_command = "processes"
 
       assign where host.name == "localhost"
     }
 
     apply Service "users" {
-      import "generic-service",
+      import "generic-service"
 
-      check_command = "users",
+      check_command = "users"
 
       assign where host.name == "localhost"
     }
 
     apply Service "disk" {
-      import "generic-service",
+      import "generic-service"
 
-      check_command = "disk",
+      check_command = "disk"
 
       assign where host.name == "localhost"
     }
index 108976ca201e5f043b9c913b20bccad7a0b3fa82..2e386c0dfe7ddf2baf4fb80c5fe296e86e6f4f34 100644 (file)
@@ -15,7 +15,7 @@ on the same physical device.
 Here is an example of a host object which defines two child services:
 
     object Host "my-server1" {
-      macros.address = "10.0.0.1",
+      macros.address = "10.0.0.1"
       check = "ping4"
     }
 
index 35ca0583f2d6f9abedae5f45b2a79071884e30b0..c3b033cb1b0f44f97579e6cdd28afde0d8279f69 100644 (file)
@@ -60,7 +60,7 @@ then use these macros on the command line.
 > be inherited from a parent template using additive inheritance (`+=`).
 
     object CheckCommand "disk" {
-      import "plugin-check-command",
+      import "plugin-check-command"
 
       command = [
         PluginDir + "/check_disk",
@@ -68,7 +68,7 @@ then use these macros on the command line.
         "-c", "$cfree$%"
       ],
 
-      macros.wfree = 20,
+      macros.wfree = 20
       macros.cfree = 10
     }
 
@@ -77,18 +77,18 @@ macros (warning thresholds at `10%`, critical thresholds at `5%` free disk
 space).
 
     object Host "localhost" {
-      import "generic-host",
+      import "generic-host"
   
-      macros.address = "127.0.0.1",
+      macros.address = "127.0.0.1"
       macros.address6 = "::1"
     }
 
     apply Service "disk" {
-      import "generic-service",
+      import "generic-service"
  
-      check_command = "disk",
+      check_command = "disk"
       
-      macros.wfree = 10,
+      macros.wfree = 10
       macros.cfree = 5
     }
     
@@ -111,9 +111,9 @@ If you require default macro definitions, you can add a macro dictionary as show
 `CheckCommand` object.
 
     object NotificationCommand "mail-service-notification" {
-      import "plugin-notification-command",
+      import "plugin-notification-command"
 
-      command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ],
+      command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ]
 
       export_macros = [
         "NOTIFICATIONTYPE",
@@ -188,19 +188,14 @@ changing the service state back to `OK` (`-r 0`) providing some debug
 information in the check output (`-o`).
 
     object EventCommand "plugin-event-process-check-result" {
-      import "plugin-event-command",
+      import "plugin-event-command"
 
       command = [ 
         PluginDir + "/process_check_result",
-        "-H",
-        "$HOSTNAME$",
-        "-S",
-        "$SERVICEDESC$",
-        "-c",
-        "/var/run/icinga2/cmd/icinga2.cmd",
-        "-r",
-        "0",
-        "-o",
-        "Event Handler triggered in state '$SERVICESTATE$' with output '$SERVICEOUTPUT$'."
+        "-H", "$HOSTNAME$",
+        "-S", "$SERVICEDESC$",
+        "-c", "/var/run/icinga2/cmd/icinga2.cmd",
+        "-r", "0",
+        "-o", "Event Handler triggered in state '$SERVICESTATE$' with output '$SERVICEOUTPUT$'."
       ]       
     }
index c2b81fb9d8720ba3db76fc48dfb7540d0442a2cf..ab1300cd1a50604a8e5cabfd5c8346f8945a4734 100644 (file)
@@ -22,7 +22,7 @@ using the available runtime macros for output formatting.
 Here is an example of a command definition which uses user-defined macros:
 
     object CheckCommand "my-ping" {
-      import "plugin-check-command",
+      import "plugin-check-command"
 
       command = [
         PluginDir + "/check_ping",
@@ -35,13 +35,13 @@ Here is an example of a command definition which uses user-defined macros:
       ],
 
       macros = {
-        wrta = 100,
-        wpl = 5,
+        wrta = 100
+        wpl = 5
 
-        crta = 200,
-        cpl = 15,
+        crta = 200
+        cpl = 15
 
-        packets = 5,
+        packets = 5
         timeout = 0
       }
     }
@@ -76,7 +76,7 @@ When using the `my-ping` command you can override all or some of the macros
 in the service definition like this:
 
     apply Service "ping" {
-      check_command = "my-ping",
+      check_command = "my-ping"
 
       macros.packets = 10 // Overrides the default value of 5 given in the command
 
index f70e6c96f4e7560423b3aa00070369b1cfac2f41..638477ec9ecebe54ea529c7fe01f3fb330e669cd 100644 (file)
@@ -23,15 +23,15 @@ The user `icingaadmin` in the example below will get notified only on `WARNING`
 `CRITICAL` states and `problem` and `recovery` notification types.
     
     object User "icingaadmin" {
-      display_name = "Icinga 2 Admin",
-      enable_notifications = 1,
-      notification_state_filter = StateFilterOK |
+      display_name = "Icinga 2 Admin"
+      enable_notifications = 1
+      notification_state_filter = (StateFilterOK |
                                   StateFilterWarning |
-                                  StateFilterCritical,
-      notification_type_filter = NotificationFilterProblem |
-                                 NotificationFilterRecovery,
+                                  StateFilterCritical)
+      notification_type_filter = (NotificationFilterProblem |
+                                 NotificationFilterRecovery)
       macros = {
-        "email" = "icinga@localhost",
+        "email" = "icinga@localhost"
         "pager" = "+49123456789"
       }
     }
@@ -59,9 +59,9 @@ There are various macros available at runtime execution of the `NotificationComm
 The example below may or may not fit your needs.
 
     object NotificationCommand "mail-service-notification" {
-      import "plugin-notification-command",
+      import "plugin-notification-command"
 
-      command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ],
+      command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ]
 
       export_macros = [
         "NOTIFICATIONTYPE",
@@ -89,14 +89,14 @@ to the defined notifications. That way you'll save duplicated attributes in each
 `Notification` object. Attributes can be overridden locally. 
     
     template Notification "generic-notification" {
-      notification_interval = 15m,
+      notification_interval = 15m
     
-      notification_command = "mail-service-notification",
+      notification_command = "mail-service-notification"
   
-      notification_state_filter = StateFilterWarning |
+      notification_state_filter = (StateFilterWarning |
                                   StateFilterCritical |
-                                  StateFilterUnknown,
-      notification_type_filter = NotificationFilterProblem |
+                                  StateFilterUnknown)
+      notification_type_filter = (NotificationFilterProblem |
                                  NotificationFilterAcknowledgement |
                                  NotificationFilterRecovery |
                                  NotificationFilterCustom |
@@ -104,7 +104,7 @@ to the defined notifications. That way you'll save duplicated attributes in each
                                  NotificationFilterFlappingEnd |
                                  NotificationFilterDowntimeStart |
                                  NotificationFilterDowntimeEnd |
-                                 NotificationFilterDowntimeRemoved,
+                                 NotificationFilterDowntimeRemoved)
   
       notification_period = "24x7"
     }
@@ -116,10 +116,10 @@ to the defined notifications. That way you'll save duplicated attributes in each
 Use the `apply` keyword to create `Notification` objects for your services:
 
     apply Notification "mail" {
-      import "generic-notification",
+      import "generic-notification"
   
-      notification_command = "mail-notification",
-      users = [ "icingaadmin" ],
+      notification_command = "mail-notification"
+      users = [ "icingaadmin" ]
 
       assign where service.short_name == "ping4"
     }
@@ -151,8 +151,8 @@ notifications between start and end time.
 > are not set in this example.
 
     object User "icinga-oncall-2nd-level" {
-      display_name = "Icinga 2nd Level",
-      enable_notifications = true,
+      display_name = "Icinga 2nd Level"
+      enable_notifications = true
 
       macros = {
         "mobile" = "+49123456781"
@@ -160,8 +160,8 @@ notifications between start and end time.
     }
     
     object User "icinga-oncall-1st-level" {
-      display_name = "Icinga 1st Level",
-      enable_notifications = true,
+      display_name = "Icinga 1st Level"
+      enable_notifications = true
 
       macros.mobile = "+49123456782"
       }
@@ -196,31 +196,31 @@ the `escalation-sms-1st-level` user will be escalated `1h` after the initial pro
 notified, but only for one hour (`2h` as `end` key for the `times` dictionary). 
 
     apply Notification "mail" {
-      import "generic-notification",
-      notification_command = "mail-notification",
-      users = [ "icingaadmin" ],
+      import "generic-notification"
+      notification_command = "mail-notification"
+      users = [ "icingaadmin" ]
   
       assign where service.short_name == "ping4"
     }
 
     apply Notification "escalation-sms-2nd-level" {
-      import "generic-notification",
-      notification_command = "sms-notification",
-      users = [ "icinga-oncall-2nd-level" ],
+      import "generic-notification"
+      notification_command = "sms-notification"
+      users = [ "icinga-oncall-2nd-level" ]
           
       times = {
-        begin = 30m,
+        begin = 30m
         end = 1h
       }
     }
 
     apply Notification "escalation-sms-1st-level" {
-      import "generic-notification",
-      notification_command = "sms-notification",
-      users = [ "icinga-oncall-1st-level" ],
+      import "generic-notification"
+      notification_command = "sms-notification"
+      users = [ "icinga-oncall-1st-level" ]
           
       times = {
-        begin = 1h,
+        begin = 1h
         end = 2h
       }
     }        
@@ -241,9 +241,9 @@ in the first 15 minutes. Leave out the `end` key - if not set, Icinga 2 will not
 end time for this notification.
 
     apply Notification "mail" {
-      import "generic-notification",
-      notification_command = "mail-notification",
-      users = [ "icingaadmin" ],
+      import "generic-notification"
+      notification_command = "mail-notification"
+      users = [ "icingaadmin" ]
           
       times.begin = 15m // delay first notification
     }
@@ -265,10 +265,10 @@ Available state and type filters for notifications are:
 
     template Notification "generic-notification" {
   
-      notification_state_filter = StateFilterWarning |
+      notification_state_filter = (StateFilterWarning |
                                   StateFilterCritical |
-                                  StateFilterUnknown,
-      notification_type_filter = NotificationFilterProblem |
+                                  StateFilterUnknown)
+      notification_type_filter = (NotificationFilterProblem |
                                  NotificationFilterAcknowledgement |
                                  NotificationFilterRecovery |
                                  NotificationFilterCustom |
@@ -276,7 +276,7 @@ Available state and type filters for notifications are:
                                  NotificationFilterFlappingEnd |
                                  NotificationFilterDowntimeStart |
                                  NotificationFilterDowntimeEnd |
-                                 NotificationFilterDowntimeRemoved,
+                                 NotificationFilterDowntimeRemoved)
     }
 
 > **Note**
index 373973cae961512197bd51b8620fe46622ef1f57..b99d76eeaaf30e4ee1ac32a38743dd931dd80c2a 100644 (file)
@@ -8,21 +8,21 @@ your hosts you can use templates to avoid having to copy & paste parts of your
 configuration:
 
     template Service "generic-service" {
-      max_check_attempts = 3,
-      check_interval = 5m,
-      retry_interval = 1m,
+      max_check_attempts = 3
+      check_interval = 5m
+      retry_interval = 1m
       enable_perfdata = true
     }
 
     apply Service "ping4" {
-      import "generic-service",
-      check_command = "ping4",
+      import "generic-service"
+      check_command = "ping4"
       assign where host.macros.address
     }
 
     apply Service "ping6" {
-      import "generic-service",
-      check_command = "ping6",
+      import "generic-service"
+      check_command = "ping6"
       assign where host.macros.address6
     }
 
index e9e3f942585b12b7b51e2e88b1b41c9dc190c76a..2b993183d90818db2384e56f7f9d3f1d1e399d13 100644 (file)
@@ -16,16 +16,13 @@ alert dashboard, first create the hostgroup:
 Then add your hosts to this hostgroup
 
     object Host "mssql-srv1" {
-      groups = [ "windows" ],
-      macros = {
-        "mssql_port" = 1433
-      }
+      groups = [ "windows" ]
+      macros.mssql_port = 1433
     }
     
     object Host "mssql-srv2" {
-      groups = [ "windows" ],
-      macros = {
-        "mssql_port" = 1433
+      groups = [ "windows" ]
+      macros.mssql_port = 1433
       }
     }
 
@@ -36,7 +33,7 @@ Then add your hosts to this hostgroup
 > You can also define multiple group memberships.
 
     template Host "windows-mssql-template" {
-      groups = [ "windows" ],
+      groups = [ "windows" ]
       macros.mssql_port = 1433
       }
     }
@@ -61,19 +58,19 @@ the user groups are associated as attributes in `Notification` objects.
     }
     
     object User "win-mssql-noc" {
-      import "generic-windows-mssql-users",
+      import "generic-windows-mssql-users"
 
       macros.email = "noc@example.com"
     }
     
     object User "win-mssql-ops" {
-      import "generic-windows-mssql-users",
+      import "generic-windows-mssql-users"
 
       macros.email = "ops@example.com"
     }
 
     apply Service "ping4" {
-      import "generic-notification",
-      notification_command = "mail-notification",
-      user_groups = [ "windows-admins" ],
+      import "generic-notification"
+      notification_command = "mail-notification"
+      user_groups = [ "windows-admins" ]
     }
index 44cb6a0e2916c99eae48fcfe172f163bdeeac534..928d1339e72172893da541a7ad0a27804789cafd 100644 (file)
@@ -32,17 +32,17 @@ on your configuration objects Icinga 2 assumes `24x7` as time period
 as shown below.
 
     object TimePeriod "24x7" {
-      import "legacy-timeperiod",
+      import "legacy-timeperiod"
 
-      display_name = "Icinga 2 24x7 TimePeriod",
+      display_name = "Icinga 2 24x7 TimePeriod"
       ranges = {
-        "monday"    = "00:00-24:00",
-        "tuesday"   = "00:00-24:00",
-        "wednesday" = "00:00-24:00",
-        "thursday"  = "00:00-24:00",
-        "friday"    = "00:00-24:00",
-        "saturday"  = "00:00-24:00",
-        "sunday"    = "00:00-24:00",
+        "monday"    = "00:00-24:00"
+        "tuesday"   = "00:00-24:00"
+        "wednesday" = "00:00-24:00"
+        "thursday"  = "00:00-24:00"
+        "friday"    = "00:00-24:00"
+        "saturday"  = "00:00-24:00"
+        "sunday"    = "00:00-24:00"
       }
     }
     
@@ -51,15 +51,15 @@ create a new timeperiod named `workhours` defining a work day with
 09:00 to 17:00.
 
     object TimePeriod "workhours" {
-      import "legacy-timeperiod",
+      import "legacy-timeperiod"
 
-      display_name = "Icinga 2 8x5 TimePeriod",
+      display_name = "Icinga 2 8x5 TimePeriod"
       ranges = {
-        "monday"    = "09:00-17:00",
-        "tuesday"   = "09:00-17:00",
-        "wednesday" = "09:00-17:00",
-        "thursday"  = "09:00-17:00",
-        "friday"    = "09:00-17:00",
+        "monday"    = "09:00-17:00"
+        "tuesday"   = "09:00-17:00"
+        "wednesday" = "09:00-17:00"
+        "thursday"  = "09:00-17:00"
+        "friday"    = "09:00-17:00"
       }
     }
 
@@ -67,10 +67,10 @@ Assign the timeperiod as `notification_period` to the `Notification`
 object then.
 
     apply Notification "mail" {
-      import "generic-notification",
+      import "generic-notification"
 
-      notification_command = "mail-notification",
-      users = [ "icingaadmin" ],
+      notification_command = "mail-notification"
+      users = [ "icingaadmin" ]
       notification_period = "workhours"
       
       assign where host.name == "localhost"
index 7fb58a9518d5563a0204f567b10c417b4806a742..ac71053eb3dc37555d2b571ab5581470e23b5165 100644 (file)
@@ -24,7 +24,7 @@ the current performance files for their backend updates.
 Therefore the Icinga 2 `PerfdataWriter` object allows you to define
 the output template format backed with Icinga 2 runtime macros.
 
-    format_template = "DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$",
+    format_template = "DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$"
     
 The default template is already provided with the Icinga 2 feature configuration
 which can be enabled using
index bb15d12528f39cbfbe6c27e6991c63097289f571..b0a8901e6dd239cd083129f56bf9c8c3c353a950 100644 (file)
@@ -26,11 +26,11 @@ overrides the `oid` macro. A service is created for all hosts which
 have the `community` macro set.
 
     apply Service "uptime" {
-      import "generic-service",
+      import "generic-service"
 
-      templates = [ "generic-service" ],
-      check_command = "snmp",
-      macros.oid = "1.3.6.1.2.1.1.3.0",
+      templates = [ "generic-service" ]
+      check_command = "snmp"
+      macros.oid = "1.3.6.1.2.1.1.3.0"
   
       assign where host.macros.community
     }
@@ -41,7 +41,7 @@ Calling a plugin using the SSH protocol to execute a plugin on the remote server
 its return code and output. `check_by_ssh` is available in the [Monitoring Plugins package](#setting-up-check-plugins).
 
     object CheckCommand "check_by_ssh_swap" {
-      import "plugin-check-command",
+      import "plugin-check-command"
 
       command = [ PluginDir + "/check_by_ssh",
                   "-l", "remoteuser",
@@ -51,10 +51,10 @@ its return code and output. `check_by_ssh` is available in the [Monitoring Plugi
     }
 
     apply Service "swap" {
-      import "generic-service",
-      check_command = "check_by_ssh_swap",
+      import "generic-service"
+      check_command = "check_by_ssh_swap"
       macros = {
-            "warn" = "50%",
+            "warn" = "50%"
             "crit" = "75%"
       }
       
@@ -76,19 +76,20 @@ remote client.
 Example:
 
     object CheckCommand "check_nrpe" {
-      import "plugin-check-command",
+      import "plugin-check-command"
 
-      command = [ PluginDir + "/check_nrpe",
-                  "-H", "$address$",
-                  "-c", "$remote_nrpe_command$",
-                ],
+      command = [
+        PluginDir + "/check_nrpe",
+        "-H", "$address$",
+        "-c", "$remote_nrpe_command$",
+      ]
     }
 
     apply Service "users" {
-      import "generic-service",
+      import "generic-service"
   
-      check_command = "check_nrpe",
-      macros.remote_nrpe_command = "check_users",
+      check_command = "check_nrpe"
+      macros.remote_nrpe_command = "check_users"
 
       assign where host.name == "remote-nrpe-host"
     }
@@ -112,32 +113,35 @@ the required output and performance counters.
 Example:
 
     object CheckCommand "check_nscp" {
-      import "plugin-check-command",
+      import "plugin-check-command"
+
+      command = [
+        PluginDir + "/check_nt",
+        "-H", "$address$",
+        "-p", "$port$",
+        "-v", "$remote_nscp_command$",
+        "-l", "$partition$",
+        "-w", "$warn$",
+        "-c", "$crit$",
+        "-s", "$pass$"
+      ]
 
-      command = [ PluginDir + "/check_nt",
-                  "-H", "$address$",
-                  "-p", "$port$",
-                  "-v", "$remote_nscp_command$",
-                  "-l", "$partition$",
-                  "-w", "$warn$",
-                  "-c", "$crit$",
-                  "-s", "$pass$"
-                ],
       macros = {
-        "port" = "12489",
+        "port" = "12489"
         "pass" = "supersecret"
       }
     }
 
     apply Service "users" {
-      import "generic-service",
+      import "generic-service"
   
-      check_command = "check_nscp",
+      check_command = "check_nscp"
+
       macros += {
-        "remote_nscp_command" = "USEDDISKSPACE",
-        "partition" = "c",
-        "warn" = "70",
-        "crit" = "80"
+        remote_nscp_command = "USEDDISKSPACE"
+        partition = "c"
+        warn = "70"
+        crit = "80"
       }
 
       assign where host.name == "remote-windows-host"
index 05ec479e2ff50d4137e21713e2ae0c602850b598..3b1fa5e19a91cd585eaa4c94d3dbcc9d8503f78a 100644 (file)
@@ -6,17 +6,28 @@ Icinga 2 features an object-based configuration format. You can define new
 objects using the `object` keyword:
 
     object Host "host1.example.org" {
-      display_name = "host1",
+      display_name = "host1"
 
       macros = {
         address = "192.168.0.1"
+        address6 = "::1"
       }
     }
 
-> **Note**
->
-> The Icinga 2 configuration format is agnostic to white space characters and
-> new-lines.
+In general you need to write each statement on a new line. Expressions started
+with `{`, `(` and `[` extend until the matching closing brace and can be broken
+up into multiple lines.
+
+Alternatively you can write multiple statements in a single line by separating
+them with a semi-colon:
+
+    object Host "host1.example.org" {
+      display_name = "host1"
+
+      macros = { address = "192.168.0.1"; address6 = "::1"; }
+    }
+
+The semi-colon after the last element (i.e. `address6`) may be omitted.
 
 > **Note**
 >
@@ -116,7 +127,7 @@ comma. The comma after the last key-value pair is optional.
 Example:
 
     {
-      address = "192.168.0.1",
+      address = "192.168.0.1"
       port = 443
     }
 
@@ -232,14 +243,14 @@ In this example a has the value 7 after both instructions are executed.
 The += operator is a shortcut. The following expression:
 
     {
-      a = [ "hello" ],
+      a = [ "hello" ]
       a += [ "world" ]
     }
 
 is equivalent to:
 
     {
-      a = [ "hello" ],
+      a = [ "hello" ]
       a = a + [ "world" ]
     }
 
@@ -248,14 +259,14 @@ is equivalent to:
 The -= operator is a shortcut. The following expression:
 
     {
-      a = 10,
+      a = 10
       a -= 5
     }
 
 is equivalent to:
 
     {
-      a = 10,
+      a = 10
       a = a - 5
     }
 
@@ -264,14 +275,14 @@ is equivalent to:
 The *= operator is a shortcut. The following expression:
 
     {
-      a = 60,
+      a = 60
       a *= 5
     }
 
 is equivalent to:
 
     {
-      a = 60,
+      a = 60
       a = a * 5
     }
 
@@ -280,14 +291,14 @@ is equivalent to:
 The /= operator is a shortcut. The following expression:
 
     {
-      a = 300,
+      a = 300
       a /= 5
     }
 
 is equivalent to:
 
     {
-      a = 300,
+      a = 300
       a = a / 5
     }
 
@@ -326,15 +337,15 @@ Example:
     }
 
     template Host "test-host" {
-      import "default-host",
+      import "default-host"
 
       macros.color = "blue"
     }
 
     object Host "localhost" {
-      import "test-host",
+      import "test-host"
 
-      macros.address = "127.0.0.1",
+      macros.address = "127.0.0.1"
       macros.address6 = "::1"
     }
 
@@ -366,9 +377,9 @@ The `apply` keyword can be used to create new objects which are associated with
 another group of objects.
 
     apply Service "ping" {
-      import "generic-service",
+      import "generic-service"
  
-      check_command = "ping4",
+      check_command = "ping4"
   
       assign where host.name == "localhost"
     }
@@ -421,7 +432,7 @@ Example:
      This is a comment.
      */
     object Host "localhost" {
-      check_interval = 30, // this is also a comment.
+      check_interval = 30 // this is also a comment.
       retry_interval = 15
     }
 
@@ -460,7 +471,7 @@ files in a directory which match a certain pattern.
 
 Example:
 
-    include_recursive "conf.d" "*.conf"
+    include_recursive "conf.d", "*.conf"
     include_recursive "templates"
 
 The first parameter specifies the directory from which files should be
index a2e6c450418455b1277937b19d1520f7cdff749b..9498b73aa74e6fe876334ec0e52717dae2628c66 100644 (file)
@@ -13,9 +13,9 @@ A host.
 Example:
 
     object Host "localhost" {
-      display_name = "The best host there is",
+      display_name = "The best host there is"
 
-      groups = [ "all-hosts" ],
+      groups = [ "all-hosts" ]
 
       check = "ping"
     }
@@ -36,7 +36,7 @@ A group of hosts.
 Example:
 
     object HostGroup "my-hosts" {
-      display_name = "My hosts",
+      display_name = "My hosts"
     }
 
 Attributes:
@@ -59,22 +59,22 @@ by Icinga 2.
 Example:
 
     object Service "localhost-uptime" {
-      host = "localhost",
-      short_name = "uptime",
+      host = "localhost"
+      short_name = "uptime"
 
-      display_name = "localhost Uptime",
+      display_name = "localhost Uptime"
 
-      check_command = "check_snmp",
+      check_command = "check_snmp"
 
       macros = {
-        community = "public",
+        community = "public"
         oid = "DISMAN-EVENT-MIB::sysUpTimeInstance"
       }
 
-      check_interval = 60s,
-      retry_interval = 15s,
+      check_interval = 60s
+      retry_interval = 15s
 
-      groups = [ "all-services", "snmp" ],
+      groups = [ "all-services", "snmp" ]
     }
 
 Attributes:
@@ -110,7 +110,7 @@ A group of services.
 Example:
 
     object ServiceGroup "snmp" {
-      display_name = "SNMP services",
+      display_name = "SNMP services"
     }
 
 Attributes:
@@ -133,10 +133,10 @@ of service state changes and other events.
 Example:
 
     object Notification "localhost-ping-notification" {
-      host = "localhost",
-      service = "ping4",
+      host = "localhost"
+      service = "ping4"
 
-      notification_command = "mail-notification",
+      notification_command = "mail-notification"
 
       users = [ "user1", "user2" ]
     }
@@ -191,13 +191,13 @@ Dependency objects are used to specify dependencies between hosts and services.
 Example:
 
     object Dependency "webserver-internet" {
-      child_host = "webserver",
-      child_service = "ping4",
+      child_host = "webserver"
+      child_service = "ping4"
 
-      parent_host = "internet",
-      parent_service = "ping4",
+      parent_host = "internet"
+      parent_service = "ping4"
 
-      state_filter = StateFilterOK,
+      state_filter = StateFilterOK
 
       disable_checks = true
     }
@@ -229,26 +229,27 @@ A user.
 Example:
 
     object User "icingaadmin" {
-      display_name = "Icinga 2 Admin",
-      groups = [ "icingaadmins" ],
+      display_name = "Icinga 2 Admin"
+      groups = [ "icingaadmins" ]
 
-      enable_notifications = 1,
-      notification_period = "24x7",
+      enable_notifications = 1
+      notification_period = "24x7"
 
-      notification_state_filter = StateFilterOK |
+      notification_state_filter = (StateFilterOK |
                                   StateFilterWarning |
                                   StateFilterCritical |
-                                  StateFilterUnknown,
-      notification_type_filter = NotificationFilterProblem |
-                                 NotificationFilterRecovery,
+                                  StateFilterUnknown)
+      notification_type_filter = (NotificationFilterProblem |
+                                 NotificationFilterRecovery)
+
       macros = {
-        "name" = "Icinga 2 Admin",
-        "email" = "icinga@localhost",
-        "pager" = "icingaadmin@localhost.localdomain"
-      },
+        name = "Icinga 2 Admin"
+        email = "icinga@localhost"
+        pager = "icingaadmin@localhost.localdomain"
+      }
 
       custom = {
-        notes = "This is the Icinga 2 Admin account.",
+        notes = "This is the Icinga 2 Admin account."
       }
     }
 
@@ -311,17 +312,18 @@ when notifications should be sent out.
 Example:
 
     object TimePeriod "24x7" {
-      import "legacy-timeperiod",
+      import "legacy-timeperiod"
+
+      display_name = "Icinga 2 24x7 TimePeriod"
 
-      display_name = "Icinga 2 24x7 TimePeriod",
       ranges = {
-        "monday"    = "00:00-24:00",
-        "tuesday"   = "00:00-24:00",
-        "wednesday" = "00:00-24:00",
-        "thursday"  = "00:00-24:00",
-        "friday"    = "00:00-24:00",
-        "saturday"  = "00:00-24:00",
-        "sunday"    = "00:00-24:00",
+        monday = "00:00-24:00"
+        tuesday = "00:00-24:00"
+        wednesday = "00:00-24:00"
+        thursday = "00:00-24:00"
+        friday = "00:00-24:00"
+        saturday = "00:00-24:00"
+        sunday = "00:00-24:00"
       }
     }
 
@@ -349,14 +351,14 @@ ScheduledDowntime objects can be used to set up recurring downtimes for services
 Example:
 
     object ScheduledDowntime "some-downtime" {
-      host = "localhost",
-      service = "ping4",
+      host = "localhost"
+      service = "ping4"
 
-      author = "icingaadmin",
-      comment = "Some comment",
+      author = "icingaadmin"
+      comment = "Some comment"
 
-      fixed = false,
-      duration = 30m,
+      fixed = false
+      duration = 30m
 
       ranges = {
         "sunday" = "02:00-03:00"
@@ -382,7 +384,7 @@ Specifies Icinga 2 logging to a file.
 Example:
 
     object FileLogger "my-debug-file" {
-      severity = "debug",
+      severity = "debug"
       path = "/var/log/icinga2/icinga2-debug.log"
     }
 
@@ -417,18 +419,18 @@ defined here.
 Example:
 
     object CheckCommand "check_snmp" {
-      import "plugin-check-command",
+      import "plugin-check-command"
 
       command = [
         PluginDir + "/check_snmp",
        "-H", "$address$",
        "-C", "$community$",
        "-o", "$oid$"
-      ],
+      ]
 
       macros = {
-        address = "127.0.0.1",
-        community = "public",
+        address = "127.0.0.1"
+        community = "public"
       }
     }
 
@@ -450,11 +452,11 @@ A notification command definition.
 Example:
 
     object NotificationCommand "mail-service-notification" {
-      import "plugin-notification-command",
+      import "plugin-notification-command"
 
       command = [
         IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh"
-      ],
+      ]
 
       export_macros = [
         "NOTIFICATIONTYPE",
@@ -494,9 +496,9 @@ An event command definition.
 Example:
 
     object EventCommand "restart-httpd-event" {
-      import "plugin-event-command",
+      import "plugin-event-command"
 
-      command = "/opt/bin/restart-httpd.sh",
+      command = "/opt/bin/restart-httpd.sh"
     }
 
 
@@ -521,11 +523,11 @@ Example:
     library "perfdata"
 
     object PerfdataWriter "pnp" {
-      perfdata_path = "/var/spool/icinga2/perfdata/service-perfdata",
+      perfdata_path = "/var/spool/icinga2/perfdata/service-perfdata"
 
-      format_template = "DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$",
+      format_template = "DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$"
 
-      rotation_interval = 15s,
+      rotation_interval = 15s
     }
 
 Attributes:
@@ -552,7 +554,7 @@ Example:
     library "perfdata"
 
     object GraphiteWriter "graphite" {
-      host = "127.0.0.1",
+      host = "127.0.0.1"
       port = 2003
     }
 
@@ -572,19 +574,19 @@ Example:
     library "db_ido_mysql"
 
     object IdoMysqlConnection "mysql-ido" {
-      host = "127.0.0.1",
-      port = 3306,
-      user = "icinga",
-      password = "icinga",
-      database = "icinga",
-      table_prefix = "icinga_",
-      instance_name = "icinga2",
-      instance_description = "icinga2 dev instance",
+      host = "127.0.0.1"
+      port = 3306
+      user = "icinga"
+      password = "icinga"
+      database = "icinga"
+      table_prefix = "icinga_"
+      instance_name = "icinga2"
+      instance_description = "icinga2 dev instance"
 
       cleanup = {
-        downtimehistory_age = 48h,
-        logentries_age = 31d,
-      },
+        downtimehistory_age = 48h
+        logentries_age = 31d
+      }
 
       categories = DbCatConfig | DbCatState
     }
@@ -656,19 +658,19 @@ Example:
     library "db_ido_pgsql"
 
     object IdoMysqlConnection "pgsql-ido" {
-      host = "127.0.0.1",
-      port = 5432,
-      user = "icinga",
-      password = "icinga",
-      database = "icinga",
-      table_prefix = "icinga_",
-      instance_name = "icinga2",
-      instance_description = "icinga2 dev instance",
+      host = "127.0.0.1"
+      port = 5432
+      user = "icinga"
+      password = "icinga"
+      database = "icinga"
+      table_prefix = "icinga_"
+      instance_name = "icinga2"
+      instance_description = "icinga2 dev instance"
 
       cleanup = {
-        downtimehistory_age = 48h,
-        logentries_age = 31d,
-      },
+        downtimehistory_age = 48h
+        logentries_age = 31d
+      }
 
       categories = DbCatConfig | DbCatState
     }
@@ -742,13 +744,13 @@ Example:
     library "livestatus"
 
     object LivestatusListener "livestatus-tcp" {
-      socket_type = "tcp",
-      bind_host = "127.0.0.1",
+      socket_type = "tcp"
+      bind_host = "127.0.0.1"
       bind_port = "6558"
     }
 
     object LivestatusListener "livestatus-unix" {
-      socket_type = "unix",
+      socket_type = "unix"
       socket_path = "/var/run/icinga2/cmd/livestatus"
     }
 
@@ -775,8 +777,8 @@ Example:
     library "compat"
 
     object StatusDataWriter "status" {
-        status\_path = "/var/cache/icinga2/status.dat",
-        objects\_path = "/var/cache/icinga2/objects.path",
+        status\_path = "/var/cache/icinga2/status.dat"
+        objects\_path = "/var/cache/icinga2/objects.path"
         update\_interval = 30s
     }
 
@@ -815,7 +817,7 @@ Example:
     library "compat"
 
     object CompatLogger "my-log" {
-      log\_dir = "/var/log/icinga2/compat",
+      log\_dir = "/var/log/icinga2/compat"
       rotation\_method = "HOURLY"
     }
 
@@ -875,7 +877,7 @@ a defined JSON file.
 Example:
 
     object IcingaStatusWriter "status" {
-      status_path = IcingaLocalStateDir + "/cache/icinga2/status.json",
+      status_path = IcingaLocalStateDir + "/cache/icinga2/status.json"
       update_interval = 15s
     }
 
@@ -897,11 +899,11 @@ Example:
     library "cluster"
 
     object ClusterListener "cluster" {
-      ca_path = "/etc/icinga2/ca/ca.crt",
-      cert_path = "/etc/icinga2/ca/icinga-node-1.crt",
-      key_path = "/etc/icinga2/ca/icinga-node-1.key",
+      ca_path = "/etc/icinga2/ca/ca.crt"
+      cert_path = "/etc/icinga2/ca/icinga-node-1.crt"
+      key_path = "/etc/icinga2/ca/icinga-node-1.key"
 
-      bind_port = 8888,
+      bind_port = 8888
 
       peers = [ "icinga-node-2" ]
     }
@@ -928,14 +930,14 @@ Example:
     library "cluster"
 
     object Endpoint "icinga-c2" {
-      host = "192.168.5.46",
-      port = 7777,
+      host = "192.168.5.46"
+      port = 7777
 
-      config_files = [ "/etc/icinga2/cluster.d/*" ],
+      config_files = [ "/etc/icinga2/cluster.d/*" ]
 
       config_files_recursive = [
         "/etc/icinga2/cluster2",
-        { path = "/etc/icinga2/cluster3", pattern = "*.myconf" }
+        { path = "/etc/icinga2/cluster3"; pattern = "*.myconf" }
       ]
     }
 
@@ -960,7 +962,7 @@ Example:
 
     object Domain "dmz-1" {
       acl = {
-        node1 = DomainPrivCheckResult,
+        node1 = DomainPrivCheckResult
         node2 = DomainPrivReadWrite
       }
     }
index 634f2d94864abf29b2260f61121a6a7d9d387b68..79a0ea67279b449fca0ab780a01b8b2e36784992 100644 (file)
@@ -74,16 +74,16 @@ recurring downtimes for services.
 Example:
 
     apply ScheduledDowntime "backup-downtime" {
-      author = "icingaadmin",
-      comment = "Scheduled downtime for backup",
+      author = "icingaadmin"
+      comment = "Scheduled downtime for backup"
 
       ranges = {
-        monday = "02:00-03:00",
-        tuesday = "02:00-03:00",
-        wednesday = "02:00-03:00",
-        thursday = "02:00-03:00",
-        friday = "02:00-03:00",
-        saturday = "02:00-03:00",
+        monday = "02:00-03:00"
+        tuesday = "02:00-03:00"
+        wednesday = "02:00-03:00"
+        thursday = "02:00-03:00"
+        friday = "02:00-03:00"
+        saturday = "02:00-03:00"
         sunday = "02:00-03:00"
       }
 
index 7727c3eac795c96071ef03ac88e3a1f0027b7cac..3b753089597100082356ed618855e75675635452 100644 (file)
@@ -75,11 +75,11 @@ A sample config part can look like this:
     library "cluster"
 
     object ClusterListener "cluster" {
-      ca_path = "/etc/icinga2/ca/ca.crt",
-      cert_path = "/etc/icinga2/ca/icinga-node-1.crt",
-      key_path = "/etc/icinga2/ca/icinga-node-1.key",
+      ca_path = "/etc/icinga2/ca/ca.crt"
+      cert_path = "/etc/icinga2/ca/icinga-node-1.crt"
+      key_path = "/etc/icinga2/ca/icinga-node-1.key"
 
-      bind_port = 8888,
+      bind_port = 8888
 
       peers = [ "icinga-node-2" ]
     }
@@ -120,8 +120,8 @@ A sample config part can look like this:
      */
 
     object Endpoint "icinga-node-1" {
-      host = "icinga-node-1.localdomain",
-      port = 8888,
+      host = "icinga-node-1.localdomain"
+      port = 8888
       config_files = ["/etc/icinga2/conf.d/*.conf"]
     }
 
@@ -135,8 +135,8 @@ A sample config part for a config receiver endpoint can look like this:
      */
 
     object Endpoint "icinga-node-2" {
-      host = "icinga-node-2.localdomain",
-      port = 8888,
+      host = "icinga-node-2.localdomain"
+      port = 8888
       accept_config = [ "icinga-node-1" ]
     }
 
@@ -163,7 +163,7 @@ Example:
     # vim cluster.conf
 
     object Endpoint "icinga-node-1" {
-      host = "icinga-node-1.localdomain",
+      host = "icinga-node-1.localdomain"
       port = 8888
     }
 
@@ -171,16 +171,16 @@ The [Endpoint](#objecttype-endpoint) name is further referenced as `peers` attri
 [ClusterListener](pbjecttype-clusterlistener) object.
 
     object Endpoint "icinga-node-2" {
-      host = "icinga-node-2.localdomain",
+      host = "icinga-node-2.localdomain"
       port = 8888
     }
 
     object ClusterListener "cluster" {
-      ca_path = "/etc/icinga2/ca/ca.crt",
-      cert_path = "/etc/icinga2/ca/icinga-node-1.crt",
-      key_path = "/etc/icinga2/ca/icinga-node-1.key",
+      ca_path = "/etc/icinga2/ca/ca.crt"
+      cert_path = "/etc/icinga2/ca/icinga-node-1.crt"
+      key_path = "/etc/icinga2/ca/icinga-node-1.key"
 
-      bind_port = 8888,
+      bind_port = 8888
 
       peers = [ "icinga-node-2" ]
     }
@@ -211,9 +211,9 @@ within the cluster, you must define `authorities` as additional service object
 attribute. Required Endpoints must be defined as array.
 
     apply Service "dmz-oracledb" {
-      import "generic-service",
+      import "generic-service"
 
-      authorities = [ "icinga-node-1" ],
+      authorities = [ "icinga-node-1" ]
 
       assign where "oracle" in host.groups
     }
@@ -234,11 +234,11 @@ one or more configured nodes are not connected.
 Example:
 
     apply Service "cluster" {
-        import "generic-service",
+        import "generic-service"
 
-        check_interval = 1m,
-        check_command = "cluster",
-        authorities = [ "icinga2a" ],
+        check_interval = 1m
+        check_command = "cluster"
+        authorities = [ "icinga2a" ]
 
         assign where host.name = "icinga2a"
     }
@@ -310,20 +310,20 @@ The configuration deployment should look like:
 The endpoint configuration on the `nuremberg` node would look like:
 
     object Endpoint "nuremberg" {
-      host = "nuremberg.icinga.org",
-      port = 8888,
+      host = "nuremberg.icinga.org"
+      port = 8888
     }
 
     object Endpoint "berlin" {
-      host = "berlin.icinga.org",
-      port = 8888,
+      host = "berlin.icinga.org"
+      port = 8888
       config_files_recursive = [ "/etc/icinga2/conf.d/templates",
                                  "/etc/icinga2/conf.d/germany/berlin" ]
     }
 
     object Endpoint "vienna" {
-      host = "vienna.icinga.org",
-      port = 8888,
+      host = "vienna.icinga.org"
+      port = 8888
       config_files_recursive = [ "/etc/icinga2/conf.d/templates",
                                  "/etc/icinga2/conf.d/austria/vienna" ]
     }
@@ -335,13 +335,13 @@ node must include the received configuration by the cluster functionality.
 Example for the configuration on the `berlin` node:
 
     object Endpoint "nuremberg" {
-      host = "nuremberg.icinga.org",
-      port = 8888,
+      host = "nuremberg.icinga.org"
+      port = 8888
     }
 
     object Endpoint "berlin" {
-      host = "berlin.icinga.org",
-      port = 8888,
+      host = "berlin.icinga.org"
+      port = 8888
       accept_config = [ "nuremberg" ]
     }
 
@@ -355,10 +355,10 @@ Example for `berlin` node connecting to central `nuremberg` node:
     library "cluster"
 
     object ClusterListener "berlin-cluster" {
-      ca_path = "/etc/icinga2/ca/ca.crt",
-      cert_path = "/etc/icinga2/ca/berlin.crt",
-      key_path = "/etc/icinga2/ca/berlin.key",
-      bind_port = 8888,
+      ca_path = "/etc/icinga2/ca/ca.crt"
+      cert_path = "/etc/icinga2/ca/berlin.crt"
+      key_path = "/etc/icinga2/ca/berlin.key"
+      bind_port = 8888
       peers = [ "nuremberg" ]
     }
 
@@ -367,10 +367,10 @@ Example for central `nuremberg` node connecting to remote nodes:
     library "cluster"
 
     object ClusterListener "nuremberg-cluster" {
-      ca_path = "/etc/icinga2/ca/ca.crt",
-      cert_path = "/etc/icinga2/ca/nuremberg.crt",
-      key_path = "/etc/icinga2/ca/nuremberg.key",
-      bind_port = 8888,
+      ca_path = "/etc/icinga2/ca/ca.crt"
+      cert_path = "/etc/icinga2/ca/nuremberg.crt"
+      key_path = "/etc/icinga2/ca/nuremberg.key"
+      bind_port = 8888
       peers = [ "berlin", "vienna" ]
     }
 
@@ -404,53 +404,53 @@ just pin them using the [authorities](#assign-services-to-cluster-nodes) attribu
 Example on the `central` node:
 
     object Endpoint "central" {
-      host = "central.icinga.org",
-      port = 8888,
+      host = "central.icinga.org"
+      port = 8888
     }
 
     object Endpoint "checker1" {
-      host = "checker1.icinga.org",
-      port = 8888,
+      host = "checker1.icinga.org"
+      port = 8888
       config_files_recursive = [ "/etc/icinga2/conf.d" ]
     }
 
     object Endpoint "checker2" {
-      host = "checker2.icinga.org",
-      port = 8888,
+      host = "checker2.icinga.org"
+      port = 8888
       config_files_recursive = [ "/etc/icinga2/conf.d" ]
     }
 
     object ClusterListener "central-cluster" {
-      ca_path = "/etc/icinga2/ca/ca.crt",
-      cert_path = "/etc/icinga2/ca/central.crt",
-      key_path = "/etc/icinga2/ca/central.key",
-      bind_port = 8888,
+      ca_path = "/etc/icinga2/ca/ca.crt"
+      cert_path = "/etc/icinga2/ca/central.crt"
+      key_path = "/etc/icinga2/ca/central.key"
+      bind_port = 8888
       peers = [ "checker1", "checker2" ]
     }
 
 Example on `checker1` node:
 
     object Endpoint "central" {
-      host = "central.icinga.org",
-      port = 8888,
+      host = "central.icinga.org"
+      port = 8888
     }
 
     object Endpoint "checker1" {
-      host = "checker1.icinga.org",
-      port = 8888,
+      host = "checker1.icinga.org"
+      port = 8888
       accept_config = [ "central" ]
     }
 
     object Endpoint "checker2" {
-      host = "checker2.icinga.org",
-      port = 8888,
+      host = "checker2.icinga.org"
+      port = 8888
       accept_config = [ "central" ]
     }
 
     object ClusterListener "checker1-cluster" {
-      ca_path = "/etc/icinga2/ca/ca.crt",
-      cert_path = "/etc/icinga2/ca/checker1.crt",
-      key_path = "/etc/icinga2/ca/checker1.key",
+      ca_path = "/etc/icinga2/ca/ca.crt"
+      cert_path = "/etc/icinga2/ca/checker1.crt"
+      key_path = "/etc/icinga2/ca/checker1.key"
       bind_port = 8888
     }
 
index 24b593d793690f12af93267571f015e8384c43a9..4e16ffcae23f337a4bdffb3087effb7c105c6a7a 100644 (file)
@@ -16,18 +16,18 @@ a different state history. `icinga-node-dmz-2` still receives all cluster messag
 from the `icinga-node-dmz-1` endpoint.
 
     object Host "dmz-host1" {
-      import "generic-host",
+      import "generic-host"
 
       services["dmz-oracledb"] = {
-        templates = [ "generic-service" ],
-        domains = [ "dmz-db" ],
-        authorities = [ "icinga-node-dmz-1", "icinga-node-dmz-2"],
+        templates = [ "generic-service" ]
+        domains = [ "dmz-db" ]
+        authorities = [ "icinga-node-dmz-1", "icinga-node-dmz-2"]
       }
     }
 
     object Domain "dmz-db" {
       acl = {
-        icinga-node-dmz-1 = DomainPrivReadOnly,
+        icinga-node-dmz-1 = DomainPrivReadOnly
         icinga-node-dmz-2 = DomainPrivReadWrite
       }
     }
index a689ef3deb65fb14dbba2b804e85153c35e033d9..b0a0187999be7a7442ff72b06958db622848c131 100644 (file)
@@ -25,11 +25,11 @@ be suppressed. This is achieved by setting the `disable_checks` attribute to `tr
     }
 
     object Host "google-dns" {
-      macros.address = "8.8.8.8",
+      macros.address = "8.8.8.8"
     }
 
     apply Service "ping4" {
-      import "generic-service",
+      import "generic-service"
 
       check_command = "ping4"
 
@@ -37,7 +37,7 @@ be suppressed. This is achieved by setting the `disable_checks` attribute to `tr
     }
 
     apply Dependency "internet" {
-      parent_host = "dsl-router",
+      parent_host = "dsl-router"
       disable_checks = true
 
       assign where host.name != "dsl-router"
index 3761e0ea6465a9fb9bd4908c5bc35266988e09fe..bb7a19178a7251c06ad230dab84f929e40f3d6d0 100644 (file)
@@ -16,10 +16,10 @@ the Icinga daemon at startup.
 Icinga 2 supports objects and (global) variables, but does not make a difference
 if it's the main configuration file, or any included file.
 
-    set IcingaEnableNotifications = 1,
+    const IcingaEnableNotifications = true
 
     object Service "test" {
-        enable_notifications = 0,
+        enable_notifications = 0
     }
 
 ### <a id="differences-1x-2-sample-configuration-itl"></a> Sample Configuration and ITL
@@ -132,8 +132,8 @@ Icinga 2 uses the keyword `import` with template names in double quotes.
     }
 
     object Service "testservice" {
-      import "tmpl1",
-      import "tmpl2",
+      import "tmpl1"
+      import "tmpl2"
       import "tmpl3"
     }
 
@@ -147,7 +147,7 @@ requires an equal sign (=) between them.
     }
 
     object Service "test" {
-        check_interval = 5m,
+        check_interval = 5m
     }
 
 > **Note**
@@ -185,13 +185,13 @@ These attributes can be set using the `custom` dictionary in Icinga 2 `Host`
 or `Service` objects:
 
     custom = {
-        notes = "Icinga 2 is the best!",
-        notes_url = "http://docs.icinga.org",
-        action_url = "http://dev.icinga.org",
-        icon_image = "../../images/logos/Stats2.png",
-        icon_image_alt = "icinga2 alt icon text",
-        "2d_coords" = "1,2",
-        statusmap_image = "../../images/logos/icinga.gif",
+        notes = "Icinga 2 is the best!"
+        notes_url = "http://docs.icinga.org"
+        action_url = "http://dev.icinga.org"
+        icon_image = "../../images/logos/Stats2.png"
+        icon_image_alt = "icinga2 alt icon text"
+        "2d_coords" = "1,2"
+        statusmap_image = "../../images/logos/icinga.gif"
     }
 
 External interfaces will recognize and display these attributes accordingly.
@@ -202,8 +202,8 @@ Icinga 1.x custom variable attributes must be prefixed using an underscore (`_`)
 In Icinga 2 these attributes must be added to the `custom`dictionary.
 
     custom = {
-        DN = "cn=icinga2-dev-host,ou=icinga,ou=main,ou=IcingaConfig,ou=LConf,dc=icinga,dc=org",
-        CV = "my custom cmdb description",
+        DN = "cn=icinga2-dev-host,ou=icinga,ou=main,ou=IcingaConfig,ou=LConf,dc=icinga,dc=org"
+        CV = "my custom cmdb description"
     }
 
 > **Note**
@@ -281,15 +281,15 @@ are separated from the command name using an exclamation mark (`!`).
 With the freely definable macros in Icinga 2 it looks like this:
 
     object CheckCommand "ping4" {
-        command = PluginDir + "/check_ping -H $HOSTADDRESS$ -w $wrta$,$wpl%$ -c $crta$,$cpl%$",
+        command = PluginDir + "/check_ping -H $HOSTADDRESS$ -w $wrta$,$wpl%$ -c $crta$,$cpl%$"
     }
 
     object Service "PING" {
-        check_command = "ping4",
+        check_command = "ping4"
         macros = {
-            wrta = 100,
-            wpl = 20,
-            crta = 500,
+            wrta = 100
+            wpl = 20
+            crta = 500
             cpl = 60
         }
     }
@@ -367,7 +367,7 @@ attribute in the object. The old way of listing all group members in the group's
 The preferred way of assigning objects to groups is by using a template:
 
     template Host "dev-host" {
-      groups += [ "dev-hosts" ],
+      groups += [ "dev-hosts" ]
     }
 
     object Host "web-dev" {
@@ -378,9 +378,9 @@ In order to associate a service with all hosts in a host group the `apply`
 keyword can be used:
 
     apply Service "ping" {
-      import "generic-service",
+      import "generic-service"
 
-      check_command = "ping4",
+      check_command = "ping4"
 
       assign where "group" in host.groups
     }
index f06abc4e75ecc894f0d5f0ec52782da7cd0bfd86..2274d57a1c1259c0384487b5c5704bfb94e3f5e8 100644 (file)
@@ -3,16 +3,16 @@
  */
 
 template ScheduledDowntime "backup-downtime" {
-  author = "icingaadmin",
-  comment = "Scheduled downtime for backup",
+  author = "icingaadmin"
+  comment = "Scheduled downtime for backup"
 
   ranges = {
-    monday = "02:00-03:00",
-    tuesday = "02:00-03:00",
-    wednesday = "02:00-03:00",
-    thursday = "02:00-03:00",
-    friday = "02:00-03:00",
-    saturday = "02:00-03:00",
+    monday = "02:00-03:00"
+    tuesday = "02:00-03:00"
+    wednesday = "02:00-03:00"
+    thursday = "02:00-03:00"
+    friday = "02:00-03:00"
+    saturday = "02:00-03:00"
     sunday = "02:00-03:00"
   }
 }
index 355f6f80e9ffee616735ede17896b116ac6887be..28be6ae8a3aad949841863400013c49f36d55b4e 100644 (file)
@@ -7,39 +7,39 @@ template Host "generic-host" {
 }
 
 apply Service "ping4" {
-  import "generic-service",
+  import "generic-service"
 
-  check_command = "ping4",
+  check_command = "ping4"
 
-  assign where "generic-host" in host.templates,
+  assign where "generic-host" in host.templates
   ignore where !host.macros.address
 }
 
 apply Service "ping6" {
-  import "generic-service",
+  import "generic-service"
 
-  check_command = "ping6",
+  check_command = "ping6"
 
-  assign where "generic-host" in host.templates,
+  assign where "generic-host" in host.templates
   ignore where !host.macros.address6
 }
 
 template Host "linux-server" {
-  import "generic-host",
+  import "generic-host"
 
-  groups += [ "linux-servers" ],
+  groups += [ "linux-servers" ]
 }
 
 template Host "windows-server" {
-  import "generic-host",
+  import "generic-host"
 
-  groups += [ "windows-servers" ],
+  groups += [ "windows-servers" ]
 }
 
 template Host "generic-printer" {
-  import "generic-host",
+  import "generic-host"
 }
 
 template Host "generic-switch" {
-  import "generic-host",
+  import "generic-host"
 }
index 33bb2b13860d75b1ffb5d7819654eb8eaad75c32..02dccc517234014c7e9b5dbb2c5567395d6584f4 100644 (file)
@@ -3,16 +3,16 @@
  * all services should import this template.
  */
 template Service "generic-service" {
-  max_check_attempts = 3,
-  check_interval = 5m,
-  retry_interval = 1m,
+  max_check_attempts = 3
+  check_interval = 5m
+  retry_interval = 1m
   enable_perfdata = true
 }
 
 apply Notification "mail-icingaadmin" {
-  import "mail-notification",
+  import "mail-notification"
 
-  user_groups = [ "icingaadmins"],
+  user_groups = [ "icingaadmins"]
 
   assign where "generic-service" in service.templates
 }
index 2f2bd6390f0570d7cf095bdf5b706ef04acbac2d..60c5f519baea8250a8aa14b0fda3c74d0ef8ee5f 100644 (file)
@@ -4,70 +4,70 @@
  * files in this directory are included.
  */
 object Host "localhost" {
-  import "linux-server",
+  import "linux-server"
 
-  macros.address = "127.0.0.1",
+  macros.address = "127.0.0.1"
   macros.address6 = "::1"
 }
 
 apply Service "icinga" {
-  import "generic-service",
+  import "generic-service"
 
-  check_command = "icinga",
+  check_command = "icinga"
 
   assign where host.name == "localhost"
 }
 
 apply Service "http" {
-  import "generic-service",
+  import "generic-service"
 
-  check_command = "http_ip",
+  check_command = "http_ip"
 
   assign where host.name == "localhost"
 }
 
 apply Service "ssh" {
-  import "generic-service",
+  import "generic-service"
 
-  check_command = "ssh",
+  check_command = "ssh"
 
   assign where host.name == "localhost"
 }
 
 apply Service "load" {
-  import "generic-service",
+  import "generic-service"
 
-  check_command = "load",
+  check_command = "load"
 
   assign where host.name == "localhost"
 }
 
 apply ScheduledDowntime "backup-downtime" {
-  import "backup-downtime",
+  import "backup-downtime"
 
   assign where service.host == "localhost" && service.short_name == "load"
 }
 
 apply Service "processes" {
-  import "generic-service",
+  import "generic-service"
 
-  check_command = "processes",
+  check_command = "processes"
 
   assign where host.name == "localhost"
 }
 
 apply Service "users" {
-  import "generic-service",
+  import "generic-service"
 
-  check_command = "users",
+  check_command = "users"
 
   assign where host.name == "localhost"
 }
 
 apply Service "disk" {
-  import "generic-service",
+  import "generic-service"
 
-  check_command = "disk",
+  check_command = "disk"
 
   assign where host.name == "localhost"
 }
index 79d363a2dd6e06368681410483cc7ae5fc08d70f..3d9b7d461a6f2abfb8ac23c5660d771fff07224d 100644 (file)
@@ -3,13 +3,13 @@
  */
 
 template Notification "mail-notification" {
-  notification_command = "mail-service-notification",
+  notification_command = "mail-service-notification"
 
-  notification_state_filter = StateFilterOK |
+  notification_state_filter = (StateFilterOK |
                                StateFilterWarning |
                                StateFilterCritical |
-                               StateFilterUnknown,
-  notification_type_filter = NotificationFilterProblem |
+                               StateFilterUnknown)
+  notification_type_filter = (NotificationFilterProblem |
                               NotificationFilterAcknowledgement |
                               NotificationFilterRecovery |
                               NotificationFilterCustom | 
@@ -17,15 +17,15 @@ template Notification "mail-notification" {
                               NotificationFilterFlappingEnd | 
                               NotificationFilterDowntimeStart |
                               NotificationFilterDowntimeEnd | 
-                              NotificationFilterDowntimeRemoved,
+                              NotificationFilterDowntimeRemoved)
 
   notification_period = "24x7"
 }
 
 object NotificationCommand "mail-service-notification" {
-  import "plugin-notification-command",
+  import "plugin-notification-command"
 
-  command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ],
+  command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ]
 
   export_macros = [
     "NOTIFICATIONTYPE",
index 1b62306d827304a5a8db2dce3662d7c7667f36f0..eb9e73d643315f3a545f2e871a8c6c2885d2a697 100644 (file)
@@ -4,37 +4,37 @@
  */
 
 object TimePeriod "24x7" {
-  import "legacy-timeperiod",
+  import "legacy-timeperiod"
 
-  display_name = "Icinga 2 24x7 TimePeriod",
+  display_name = "Icinga 2 24x7 TimePeriod"
   ranges = {
-    "monday"   = "00:00-24:00",
-    "tuesday"  = "00:00-24:00",
-    "wednesday" = "00:00-24:00",
-    "thursday"         = "00:00-24:00",
-    "friday"   = "00:00-24:00",
-    "saturday"         = "00:00-24:00",
-    "sunday"   = "00:00-24:00",
+    "monday"   = "00:00-24:00"
+    "tuesday"  = "00:00-24:00"
+    "wednesday" = "00:00-24:00"
+    "thursday"         = "00:00-24:00"
+    "friday"   = "00:00-24:00"
+    "saturday"         = "00:00-24:00"
+    "sunday"   = "00:00-24:00"
   }
 }
 
 object TimePeriod "9to5" {
-  import "legacy-timeperiod",
+  import "legacy-timeperiod"
 
-  display_name = "Icinga 2 9to5 TimePeriod",
+  display_name = "Icinga 2 9to5 TimePeriod"
   ranges = {
-    "monday"   = "09:00-17:00",
-    "tuesday"  = "09:00-17:00",
-    "wednesday" = "09:00-17:00",
-    "thursday"         = "09:00-17:00",
-    "friday"   = "09:00-17:00",
+    "monday"   = "09:00-17:00"
+    "tuesday"  = "09:00-17:00"
+    "wednesday" = "09:00-17:00"
+    "thursday"         = "09:00-17:00"
+    "friday"   = "09:00-17:00"
   }
 }
 
 object TimePeriod "never" {
-  import "legacy-timeperiod",
+  import "legacy-timeperiod"
 
-  display_name = "Icinga 2 never TimePeriod",
+  display_name = "Icinga 2 never TimePeriod"
   ranges = {
   }
 }
index 4e427adcbb8e4a273ebfefaf38b428e8ca3c45e9..dbe676f08ce6338b17cd701c61336b6b8859f8ed 100644 (file)
@@ -4,19 +4,19 @@
  */
 
 object User "icingaadmin" {
-  import "generic-user",
+  import "generic-user"
 
-  display_name = "Icinga 2 Admin",
-  groups = [ "icingaadmins" ],
+  display_name = "Icinga 2 Admin"
+  groups = [ "icingaadmins" ]
 
   macros = {
-    "name" = "Icinga 2 Admin",
-    "email" = "icinga@localhost",
+    "name" = "Icinga 2 Admin"
+    "email" = "icinga@localhost"
     "pager" = "icingaadmin@localhost.localdomain"
-  },
+  }
 
   custom = {
-    notes = "This is the Icinga 2 Admin account.",
+    notes = "This is the Icinga 2 Admin account."
   }
 }
 
index 49aaa8d3bd8c4a6b0d33bba59751b3b8f3f4f143..a511dd660db6cbb5b7f2c0ad545ce4a9c78aa00b 100644 (file)
@@ -29,7 +29,7 @@ include "features-enabled/*.conf"
 /**
  * Although in theory you could define all your objects in this file
  * the preferred way is to create separate directories and files in the conf.d
- * directory.
+ * directory. Each of these files must have the file extension ".conf".
  */
-include_recursive "conf.d" "*.conf"
+include_recursive "conf.d"
 
index 298a02f08e33fbc91280f7aad876996b9ca24c90..510a484d3e061f3357540808e39098b30b718e2f 100644 (file)
@@ -45,6 +45,8 @@ do {                                                  \
        result = yyextra->ReadInput(buf, max_size);     \
 } while (0)
 
+extern int ignore_newlines;
+
 struct lex_buf {
        char *buf;
        size_t size;
@@ -194,7 +196,7 @@ static char *lb_steal(lex_buf *lb)
 
 
 \/\/[^\n]*                     /* ignore C++-style comments */
-[ \t\r\n]                      /* ignore whitespace */
+[ \t]                          /* ignore whitespace */
 
 <INITIAL>{
 %type                          return T_TYPE;
@@ -259,6 +261,7 @@ in                          { yylval->op = &AExpression::OpIn; return T_IN; }
 \>                             { yylval->op = &AExpression::OpLessThan; return T_GREATER_THAN; }
 }
 
+[\r\n]+                                { if (!ignore_newlines) return T_NEWLINE; }
 .                              return yytext[0];
 
 %%
index a40feddb390295af567481ed454ec29b759aa50f..4a56e2005dab0ff6757e91b754c34e04659fa81c 100644 (file)
@@ -69,6 +69,8 @@ do {                                                  \
 
 using namespace icinga;
 
+int ignore_newlines = 0;
+
 static void MakeRBinaryOp(Value** result, AExpression::OpCallback& op, Value *left, Value *right, DebugInfo& diLeft, DebugInfo& diRight)
 {
        *result = new Value(make_shared<AExpression>(op, static_cast<AExpression::Ptr>(*left), static_cast<AExpression::Ptr>(*right), DebugInfoRange(diLeft, diRight)));
@@ -97,6 +99,7 @@ static void MakeRBinaryOp(Value** result, AExpression::OpCallback& op, Value *le
        Array *array;
 }
 
+%token T_NEWLINE "new-line"
 %token <text> T_STRING
 %token <text> T_STRING_ANGLE
 %token <num> T_NUMBER
@@ -185,6 +188,7 @@ static void MakeRBinaryOp(Value** result, AExpression::OpCallback& op, Value *le
 %left T_MULTIPLY T_DIVIDE_OP
 %right '!' '~'
 %left '.' '(' '['
+%right ':'
 %{
 
 int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
@@ -232,7 +236,7 @@ statements: /* empty */
        | statements statement
        ;
 
-statement: type | include | include_recursive | library | constant
+statement: type | include | include_recursive | library | constant | newlines
        { }
        | lterm
        {
@@ -242,7 +246,7 @@ statement: type | include | include_recursive | library | constant
        }
        ;
 
-include: T_INCLUDE rterm
+include: T_INCLUDE rterm sep
        {
                AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$2);
                delete $2;
@@ -263,26 +267,26 @@ include_recursive: T_INCLUDE_RECURSIVE rterm
 
                context->HandleIncludeRecursive(aexpr->Evaluate(m_ModuleScope), "*.conf", DebugInfoRange(@1, @2));
        }
-       | T_INCLUDE_RECURSIVE rterm rterm
+       | T_INCLUDE_RECURSIVE rterm ',' rterm
        {
                AExpression::Ptr aexpr1 = static_cast<AExpression::Ptr>(*$2);
                delete $2;
 
-               AExpression::Ptr aexpr2 = static_cast<AExpression::Ptr>(*$3);
-               delete $3;
+               AExpression::Ptr aexpr2 = static_cast<AExpression::Ptr>(*$4);
+               delete $4;
 
-               context->HandleIncludeRecursive(aexpr1->Evaluate(m_ModuleScope), aexpr2->Evaluate(m_ModuleScope), DebugInfoRange(@1, @3));
+               context->HandleIncludeRecursive(aexpr1->Evaluate(m_ModuleScope), aexpr2->Evaluate(m_ModuleScope), DebugInfoRange(@1, @4));
        }
        ;
 
-library: T_LIBRARY T_STRING
+library: T_LIBRARY T_STRING sep
        {
                context->HandleLibrary($2);
                free($2);
        }
        ;
 
-constant: T_CONST identifier T_SET rterm
+constant: T_CONST identifier T_SET rterm sep
        {
                AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$4);
                delete $4;
@@ -316,7 +320,7 @@ type: partial_specifier T_TYPE identifier
                        m_Type->Register();
                }
        }
-       type_inherits_specifier typerulelist
+       type_inherits_specifier typerulelist sep
        {
                TypeRuleList::Ptr ruleList = *$6;
                m_Type->GetRuleList()->AddRules(ruleList);
@@ -353,11 +357,11 @@ typerulelist: '{'
        ;
 
 typerules: typerules_inner
-       | typerules_inner ','
+       | typerules_inner sep
 
 typerules_inner: /* empty */
        | typerule
-       | typerules_inner ',' typerule
+       | typerules_inner sep typerule
        ;
 
 typerule: T_REQUIRE T_STRING
@@ -418,7 +422,7 @@ object:
        {
                m_Abstract = false;
        }
-       object_declaration identifier rterm rterm_scope
+       object_declaration identifier rterm rterm_scope sep
        {
                Array::Ptr args = make_shared<Array>();
                
@@ -486,14 +490,11 @@ lbinary_op: T_SET
        }
        ;
 
-comma_or_semicolon: ',' | ';'
-       ;
-
 lterm_items: lterm_items_inner
        {
                $$ = $1;
        }
-       | lterm_items_inner comma_or_semicolon
+       | lterm_items_inner sep
        {
                $$ = $1;
        }
@@ -508,7 +509,7 @@ lterm_items_inner: /* empty */
                $$->Add(*$1);
                delete $1;
        }
-       | lterm_items_inner comma_or_semicolon lterm
+       | lterm_items_inner sep lterm
        {
                if ($1)
                        $$ = $1;
@@ -624,17 +625,31 @@ rterm_items_inner: /* empty */
        }
        | rterm_items_inner ',' rterm
        {
-               if ($1)
-                       $$ = $1;
-               else
-                       $$ = new Array();
-
+               $$ = $1;
                $$->Add(*$3);
                delete $3;
        }
+       | rterm_items_inner ',' newlines rterm
+       {
+               $$ = $1;
+               $$->Add(*$4);
+               delete $4;
+       }
        ;
 
-rterm_scope: '{' lterm_items '}'
+rterm_scope: '{' newlines lterm_items newlines '}'
+       {
+               $$ = new Value(make_shared<AExpression>(&AExpression::OpDict, Array::Ptr($3), DebugInfoRange(@1, @5)));
+       }
+       | '{' newlines lterm_items '}'
+       {
+               $$ = new Value(make_shared<AExpression>(&AExpression::OpDict, Array::Ptr($3), DebugInfoRange(@1, @4)));
+       }
+       | '{' lterm_items newlines '}'
+       {
+               $$ = new Value(make_shared<AExpression>(&AExpression::OpDict, Array::Ptr($2), DebugInfoRange(@1, @4)));
+       }
+       | '{' lterm_items '}'
        {
                $$ = new Value(make_shared<AExpression>(&AExpression::OpDict, Array::Ptr($2), DebugInfoRange(@1, @3)));
        }
@@ -686,6 +701,18 @@ rterm: T_STRING
                delete $1;
                free($3);
        }
+       | '[' newlines rterm_items newlines ']'
+       {
+               $$ = new Value(make_shared<AExpression>(&AExpression::OpArray, Array::Ptr($3), DebugInfoRange(@1, @5)));
+       }
+       | '[' rterm_items newlines ']'
+       {
+               $$ = new Value(make_shared<AExpression>(&AExpression::OpArray, Array::Ptr($2), DebugInfoRange(@1, @4)));
+       }
+       | '[' newlines rterm_items ']'
+       {
+               $$ = new Value(make_shared<AExpression>(&AExpression::OpArray, Array::Ptr($3), DebugInfoRange(@1, @4)));
+       }
        | '[' rterm_items ']'
        {
                $$ = new Value(make_shared<AExpression>(&AExpression::OpArray, Array::Ptr($2), DebugInfoRange(@1, @3)));
@@ -694,9 +721,14 @@ rterm: T_STRING
        {
                $$ = $1;
        }
-       | '(' rterm ')'
+       | '('
        {
-               $$ = $2;
+               ignore_newlines++;
+       }
+       rterm ')'
+       {
+               ignore_newlines--;
+               $$ = $3;
        }
        | rterm T_LOGICAL_OR rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
        | rterm T_LOGICAL_AND rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
@@ -793,4 +825,18 @@ apply:
                m_Assign.reset();
                m_Ignore.reset();
        }
+       ;
+
+newlines: T_NEWLINE
+       | newlines T_NEWLINE
+       ;
+
+/* required separator */
+sep: ',' newlines
+       | ','
+       | ';' newlines
+       | ';'
+       | newlines
+       ;
+
 %%