Apply Service for every User in Icinga2

Hey Guys :wave:,

My team and I want to create an Icinga2 Service for every Icinga User so we can monitor the alerts targets at PagerDuty.
We have tried a lot of things, and can’t seem to figure it out.
The closes we have got is this:

apply Service for (u in get_objects(User)) {
    name = "PagerDuty-Practices-" + u.name
    host_name = "icinga2master.local"
    check_command = "check_user_practices"
    vars.user = u.name
}

For some reason this code runs many more times than it should, and fails on the following log:

[2021-07-20 12:01:44 +0000] critical/config: Error: An object with type 'Service' and name 'icinga2master.local!PagerDuty-Practices-[some user's name]' already exists (in /etc/icinga2/conf.d/apply_check_pagerduty_practices.conf: 8:1-8:42), new declaration: in /etc/icinga2/conf.d/apply_check_pagerduty_practices.conf: 8:1-8:42
Location: in /etc/icinga2/conf.d/apply_check_pagerduty_practices.conf: 8:1-8:42
/etc/icinga2/conf.d/apply_check_pagerduty_practices.conf(6): }
/etc/icinga2/conf.d/apply_check_pagerduty_practices.conf(7): 
/etc/icinga2/conf.d/apply_check_pagerduty_practices.conf(8): apply Service for (u in get_objects(User)) {
                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/etc/icinga2/conf.d/apply_check_pagerduty_practices.conf(9):     name = "PagerDuty-Practices-" + u.name
/etc/icinga2/conf.d/apply_check_pagerduty_practices.conf(10):     host_name = "icinga2master.local"

This log is printed multiple times for every user.

We would appreciate suggestions to achieve want we are looking for.
Thank You!

The problem is an apply is tested for every host, so this is likely the reason why it creates duplicates.

I would try to run a loop and create an object instead of apply in this.

So not tested and inspired by icinga-vagrant/many.conf.erb at master · Icinga/icinga-vagrant · GitHub :

for (u in get_objects(User)) {
  object Service "PagerDuty-Practices-" + u.name use u {
    host_name = "icinga2master.local"
    check_command = "check_user_practices"
    vars.user = u.name
  }
}

Thank you for your answer @dgoetz !
I have added () to

use (u)

and the configuration was verified.
However, I don’t see any services created, and after adding log() to the loop nothing gets printed.
logging get_objects(User) doesn’t return anything either.
I guess you can’t use that function outside of an apply rule because of scope\context?
I added this loop to a .conf file, not inside anything.

Edit:
After looking online (Getting a list of hosts inside config) I understand we can’t get objects natively from the DSL because Icinga runs that before the objects are being created. Any ideas how I can run this logic after the Users have been created?

Unfortunately no, but perhaps @Al2Klimov does know a trick how to get this.

I found a way to achieve my goal.
Because I want all the services to run on the same Host, PagerDuty API, I just added an assign line like this:

apply Service "PagerDuty-Practices-" for (u in get_objects(User)) to Host {
  name = "PagerDuty-Practices-" + u.name
  check_command = "check_pagerduty_practices"
  vars.user = u.name
  vars.critical_notification = ["team-devops-low"]
  assign where host.name == "pagerduty.com"
}

Thank You!