Syntax question: variable as a command argument

Hi all,
some environment information first:
Icinga version: 2.11.3-1
OS: RHEL 7.6

Issue: I’m trying to configure a command to set a parameter using a variable content (string) as name, if the variable is filled.

Requirements:
The generated command should be either:
${PluginDir}/check_os_bond_mon #if variable is empty
or
${PluginDir}/check_os_bond_mon <variable_content> #if variable is filled

Just adding the variable to the command is not the solution, because this will cause an empty string being added, if the variable is empty. This empty string will be counted as an argument, which will cause the script to change its behaviour and to evaluate this “empty” parameter.

Example:

command = [ PluginDir + "/check_os_bond_mon", "$bond_iface_name$" ]

leads to:
${PluginDir}/check_os_bond_mon ‘’

instead of just:
${PluginDir}/check_os_bond_mon
if the variable is empty.

My command config:

object CheckCommand "os_bond" {
  import "plugin-check-command"
  command = [ PluginDir + "/check_os_bond_mon" ]
  arguments += {
    "$bond_iface_name$" = {
      set_if = "$os_bond_iface_name$"
    }
  }
  vars.bond_iface_name = "$os_bond_iface_name$"
}

I tried following strings as argument name so far:

"$bond_iface_name$" = {
"$os_bond_iface_name$" = {
"macro($bond_iface_name$)" = {
"macro($os_bond_iface_name$)" = {

All those lines are accepted by “icinga2 daemon -C”, but none of it is adding the string, if the variable is filled. What’s the correct syntax to beam the variable content into the argument name?

Thanks a lot.
Best regards,
Dirk

The following hasn’t been tested, but please try:

object CheckCommand "os_bond" {
  import "plugin-check-command"
  command = [ PluginDir + "/check_os_bond_mon" ]
  if (vars.bond_iface_name) {
    command += [vars.bond_iface_name]
  }
}

The same should actually work with arguments too.

Also if the $$ expansion won’t work with setif (sometimes it doesn’t and I’ve never figured out why), you may try set_if = {{ if ( "$some_variable$" ) { return 1 } else { return 0 } }}.

Hi Matlib,

thanks a lot for the recommendation. The syntax is accepted by “icinga2 daemon -C”, but when loaded into icinga, the “if”-block is removed completely from the (external) command. No error messages, it is just not there. I still ran a test, but the variable was not added to the command, as expected.

I tried the expansion tip as well, but this causes the command to show up in the gui with the following line:

set_if = "/* Unable to fetch function body through API */"

Any other tips are much appreciated.

Thank you.
Regards,
Dirk

Hi all,
after stressing the docs I found a solution:

arguments += {
  "--dummy" = {
    value = $os_bond_iface_name$"
    skip_key = true
  }
}

The “skip_key” causes the key “–dummy” not to be displayed. Vor any reason in this configuration no empty string is added, if the variable is not filled.
Hint: Using “set_if” will cause this to fail, because this is removing the value, so nothing is added.

Regards,
Dirk

I had to dig a little too.

  1. CheckCommand has its own vars so the condition will (quite obviously) not work.

  2. The set_if trick would work, and in fact I use it a lot, however the expansion cannot be used on the left side of the argument hash (the command just receives literal $os_bond_iface_name$, see below).
    And the reason why direct feed to set_if works ”sometimes“ is this:

Argument is added if the runtime macro string resolves to a defined numeric or boolean value. String values are not supported. Function calls returning a value are supported too.

Others may find it useful, so I’m pasting my test bench too.

check_test

#!/bin/sh
echo TEST OK
i=1
for a in "$@"
do
    printf '%02d "%s"\n' $i "$a"
    let i=i+1 > /dev/null
done
exit 0

test.conf

object CheckCommand "test" {
    command = [ PluginContribDir + "/check_test" ]
    arguments = {
        "$os_bond_iface_name$" = {
            set_if = {{ if ( "$os_bond_iface_name$" ) { return 1 } else { return 0 } }}
        }
    }
}

And this produces the following output:

Plugin Output
TEST OK
01 "$os_bond_iface_name$"