Function returning string

Hi!
At the moment I’m completely messed up which syntax I’ve to use in a function to get values of variables based on some conditions and how to return it as a string.
icinga2 - The Icinga 2 network monitoring daemon (version: r2.13.3-1)

The function “use_ext_IP” should return either the external IP address of a router, if the host variable “vars.address_ext” isn’t empty and if … or the host variable address.

The service has state ok and delivers exptected values, but as display_name I see “Service: Object of type ‘Function’ …”. And I don’t know which IP address was used.

object Host “rt-lte-01” {
address = “10.10.10.10”
vars.address_ext = “30.30.30.30”
vars.connection_type = “LTE”

}

apply Service “snmp-ext” to Host {
check_command = “snmp-statistic-ext”
vars.snmp_oid = “1.3.6.1.4.1.1.2.3.4.5.6.7.8.9”
display_name = use_ext_IP() # or {{ use_ext_IP() }}
vars.snmp_host = use_ext_IP()

assign where host.name == “rt-lte-01”
}

function use_ext_IP() {
var snmp_host = {{ host.address }} # or “$address$” or macro(“$address$”)
if ( {{ connection_type }} == “LTE” ) {
if ( “$address_ext$” != “” ) {
if ( “$hostname$” == “rt-lte-01” ) {
snmp_host = {{ vars.address_ext }}
}
}
}
return snmp_host
}

object CheckCommand “snmp-statistic-ext” {
command = [ PluginDir + “/check_snmp” ]
arguments = {
“-H” = “$snmp_host$”
“-o” = “$snmp_oid$”
“-l” = {
set_if = {{ “$snmp_label$” != “” }}
value = “$snmp_label$”
}

}
}

Hi & welcome,

You don’t need an external function here. You can directly check address_ext within your service object like this:

if (host.vars.address_ext) {
   display_name = host.vars.address_ext
   vars.snmp_host = host.vars.address_ext
} else {
   display_name = host.address
   vars.snmp_host = host.address
}

And instead of assigning a host directly, you could (re)use the host variable like this:

assign where host.vars.connection_type == “LTE”

Hi Roland,
thanks for your answer.
Will the syntax you proposed also work in a function?
I’ll give it a try.

The simple reason to use a function for that is, that I’ve several services where I don’t want to repeat the if else structure, especially because I could make changes in the future and add additional services.

Kind regards,
Peter

Hi Roland,
within a function your proposed syntax don’t work.

[2023-02-16 09:38:35 +0100] critical/config: Error: Error while evaluating expression: Tried to access undefined script variable 'host'
Location: in /etc/icinga2/conf.d/services/cisco-router.conf: 125:19-125:22

/etc/icinga2/conf.d/services/cisco-router.conf(125):   var snmp_host = host.address
                                                                       ^^^^

Kind regards,
Peter

I think you need to wrap it in a macro() like:

var snmp_host = macro("$address$")

https://icinga.com/docs/icinga-2/latest/doc/18-library-reference/#macro

Hi Dominik,
thanks for your answer, but it still gives an error.

[2023-02-16 10:00:13 +0100] critical/config: Error: Argument is not a callable object.
Location: in /etc/icinga2/conf.d/services/cisco-router.conf: 124:19-124:36
/etc/icinga2/conf.d/services/cisco-router.conf(122): function use_ext_IP() {
/etc/icinga2/conf.d/services/cisco-router.conf(123):   # invalid syntax: "$address$", host.address, {{ host.address }}
/etc/icinga2/conf.d/services/cisco-router.conf(124):   var snmp_host = macro("$address$")
                                                                       ^^^^^^^^^^^^^^^^^^

Kind regards,
Peter

Hi!
Within my function (see first post) I don’t get errors for these syntaxes:

var snmp_host = {{ host.address }}
var snmp_host = this.host.address

But I don’t have a clue which one does what and which one to use when.

Kind regards,
Peter

You could use a template instead of a function e.g.:

template Service "ipselect" {
    if (host.vars.address_ext) {
        display_name = host.vars.address_ext
        vars.snmp_host = host.vars.address_ext
    } else {
        display_name = host.address
        vars.snmp_host = host.address
    }
}

and use it in any service object with import:

import “ipselect”

1 Like

Hi Roland,
thanks for your hint.
With such a service template I could solve it.

Kind regards,
Peter