Error when adding an apply rule: "Invalid field access (for value of type 'String'): 'org'"

Hey All,
I need help with an apply rule I’m writing. I tried to follow the documentation, and created something very similar. This is the apply rule:

apply Service "dummy" for (check => config in host.vars.object) {
  import "generic-service"
  assign where host.vars.object
  check_command = "check_prometheus"
  display_name = "dummy - " + config.org
  params = {
    "warning_threshold" = "1",
    "critical_threshold" = "5",
    "check_interval" = "1h",
    "query" = "<redacted>",
    "method" = "gt",
  }

  vars += params

  action_url = "<redacted>"+config.org+"<redacted>"+config.project

  check_interval = 1d
  max_check_attempts = 3
  retry_interval = 5m

  enable_notifications = true
  enable_perfdata = true
  name = check
}

And this is the vars I’m adding to an host (using Puppet module to translate a JSON to icinga DSL):

"vars": {
    "object": {
                    "project": "<redacted>",
                    "org": "<redacted>"
                }
}

I have no idea why, but Icinga failed to parse my apply rule:

critical/config: Error: Invalid field access (for value of type 'String'): 'org'|
|---|---|
 Location: in /etc/icinga2/conf.d/apply_object.conf: 5:44-5:53|
 /etc/icinga2/conf.d/apply_object.conf(3):   assign where host.vars.object|
/etc/icinga2/conf.d/apply_object.conf(4):   check_command = "check_prometheus"|
/etc/icinga2/conf.d/apply_object.conf(5):   display_name = "dummy - " + config.org|
                                                                                  ^^^^^^^^^^|
 /etc/icinga2/conf.d/apply_object.conf(6):   params = {|
/etc/icinga2/conf.d/apply_object.conf(7):     "warning_threshold" = "1",|

Could you help me figure out what the issue is?

Thanks in advance!
Omer

You have another host object which has vars.object specified, but they key org doesn’t exist in it.

Try adding a sanity check plus debug logging into the apply rule to figure out where this comes from.

  if (!config.contains("org")) {
    log(LogWarning, "config", "Host " + host.name + " does not provide the 'org' key in the 'object' dictionary.")
  } else {
    action_url = "<redacted>"+config.org+"<redacted>"+config.project
  }

Run a manual config validation then to have this logged into the terminal.

Same checks are needed for the project key btw.

Cheers,
Michael

Thanks, you’re reply led me in the right direction. Apparently, the following JSON:

"vars": {
    "object": {
                    "project": "<redacted>",
                    "org": "<redacted>"
                }
}

Will be translated into the following icinga object:

vars.object["project"] = <redacted>
vars.object["org"] = <redacted>

So what I was getting in the config was just the string value , each time for a different property. I need to play a bit with the syntax to understand how exactly specify what I want.

Thanks!

That’s basically the same notation. Either you’ll have

vars = {
  "object" = {
     "project" = "..."
     "org" = "...."
   }
}

or you’ll access (and create if not existing) the dictionary keys using square brackets:

vars.object["project"] = "..."
vars.object["org"] = "..."

or you’ll use the indexer dot in the same way. Square brackets have the advantage when double quotes are needed, e.g. when the key contains a dash.

vars.object.project = "..."
vars.object.org = "..."

In either way, if your apply rule relies on the given values, you need to have sanitizers in place. Your users or scripts may use the generic attribute name “object” in different meanings. I’d also opt for a different attribute name here to avoid possible complications with “object” being either a dictionary, array or string.

Cheers,
Michael