Icinga and Director - Variable is not detected (?)

HI,

I have a strange problem where the following config not add the -C Argument to the by_ssh check. Only if use override vars inside the director with exact the same value its working:


object CheckCommand "by_ssh_director_o" {
    import "plugin-check-command"
    import "by_ssh_director"

    vars.by_ssh_identity = "/var/lib/nagios/.ssh/mon.id_rsa"
    vars.by_ssh_logname = "mon"
    vars.by_ssh_options = "StrictHostKeyChecking=no"
}

object CheckCommand "by_ssh_director" {
        import "ipv4-or-ipv6"

        command = [ PluginDir + "/check_by_ssh" ]

        arguments = {
                "-H" = {
                        value = "$host.address$"
                        description = "Host name, IP Address, or unix socket (must be an absolute path)"
                }
                "-p" = {
                        value = "$by_ssh_port$"
                        description = "Port number (default: none)"
                }
                "-C" = {
                         value = "$by_ssh_command$" + " " + "$by_ssh_arguments$"
                        description = "The Check Command including path and Arguments"
                }
                "-l" = {
                        value = "$by_ssh_logname$"
                        description = "SSH user name on remote host [optional]"
                }
                "-i" = {
                        value = "$by_ssh_identity$"
                        description = "identity of an authorized key [optional]"
                }
                "-q" = {
                        set_if = "$by_ssh_quiet$"
                        description = "Tell ssh to suppress warning and diagnostic messages [optional]"
                }
                "-w" = {
                        value = "$by_ssh_warn$"
                        description = "Response time to result in warning status (seconds)"
                }
                "-c" = {
                        value = "$by_ssh_crit$"
                        description = "Response time to result in critical status (seconds)"
                }
                "-t" = {
                        value = "$by_ssh_timeout$"
                        description = "Seconds before connection times out (default: 10)"
                }
                "-o" = {
                        value = "$by_ssh_options$"
                        description = "Provide ssh options (may be repeated)"
                }
                "-4" = {
                        set_if = true
                        description = "Use IPv4 only"
                }
                "-6" = {
                        set_if = "$by_ssh_ipv6$"
                        description = "Use IPv6 only"
                }
                "-E" = {
                        value = "$by_ssh_skip_stderr$"
                        description = "Ignore all or (if specified) first n lines on STDERR [optional]"
                }
        }

        vars.by_ssh_quiet = false
}


template Service "disk_all_sap_ssh" {
    import "generic-service"

    check_command = "by_ssh_director_o"
    check_interval = 10m
    icon_image = "disk.png"
    vars.by_ssh_arguments = "-c 10% -u GB -x tracefs --icritical=5% -A  -I 'gvfs'"
    vars.by_ssh_command = "$host.plugin_directory$/check_disk"
}



inspect command is showing:

‘/usr/lib/nagios/plugins/check_by_ssh’ ‘-4’ ‘-H’ ‘HOSTNAME’ ‘-i’ ‘/var/lib/nagios/.ssh/mon.id_rsa’ ‘-l’ ‘mon’ ‘-o’ ‘StrictHostKeyChecking=no’

So the “-C” Parameter is missing.

Now, when i override the vars.by_ssh_command = “$host.plugin_directory$/check_disk” with the exact same value in the director, its working again.

Looks suspicious. If that runtime macro doesn’t resolve, -C will remain undefined because it references the undefined by_ssh_command.

Apart from that, the string concat between command and arguments looks fairly strange.

1 Like

Hi, thanks for the VERY fast answer. I posted it by accident. My post wasn’t ready, so i needed to edit a little bit more :slightly_smiling_face:

Yes, that line is exacly the problem. Without a variable inside it, its working. As its working again, when I’am overriding it with the director, it looks like a problem with order (reihenfolge).

Have you tried escaping th $ signs (with more $ signs :wink: )?

vars.by_ssh_command = “$$host.plugin_directory$$/check_disk”

1 Like

As its working exacly the same way if i override it, the problem is not the correct escaping I think.

Solved it, by changing this line:
´´´
value = “$by_ssh_command$” + " " + “$by_ssh_arguments$”
´´´
to this:
´´´
value = “$host.vars.plugin_directory$” + “/” + “$by_ssh_command$” + " " + “$by_ssh_arguments$”
´´´
and remove the plugin_directory everywhere else.

Ah, missing .vars in between. I’m not really focused today, just deep down in my Windows exception stack.

Good thing you found it :+1:
I noticed the missing .vars, but got a bit confused as @dnsmichi was talking about runtime macros and I wasn’t sure how those have to be specified^^

When you look at

“$host.plugin_directory$/check_disk”

the macro resolver parses this as $...$ and takes the inner string as lookup value from available resolver lists. Icinga has specific resolver lists registered for a scope (e.g. a host or service check).

Either you define host. or service. as prefix, then Icinga knows that an object type is meant for the attributes defined after. Or you’ll have a full string without type indexer prefix, then it does a list iteration and finds the first match.

That being said, the above looks for the host object and then for plugin_directory as object attribute. This doesn’t exist for hosts and as such, it will not resolve. Icinga returns an error and logs a warning to icinga2.log. Since the resolving failed, any other runtime macro recursively pointing to it, will also fail.

Such recursive runtime macros are a hell to debug, that is why we commonly don’t try to chain it that much. Also, the string parsing inside the macro resolve is really expensive, splitting the string, extracting the macros, doing the lookups, etc.

Therefore we recommend to rather calculate them within the DSL, or have them pre-calculated with the config compiler, e.g. with using a global constant which immediately gets resolved. Sometimes this isn’t possible though.

Cheers,
Michael

2 Likes

Thanks for the explanation! :+1:

Yes, looks like i wasn’t focused too. Writing a forum post instead of just read what i’ve done was not the fastest way to solve that :wink:

Still not sure why it was working after copy & paste it in the directory override. Not idea where i copied the correct one :slight_smile:

Thank you both for your Time :slight_smile: