Scope of get_service function within config file outside of icinga2 console

Dear Icinga community,

I am trying to learn DSL scripting, and I can not fully understand what is the “scope” of a function when I create a custom global function using pre-defined functions from the DSL library and place such script into a configuration file. Probably it is something simple for advanced users, but for me it is unclear what I should change in the script to do things in the right scope.

Namely, when I copy-paste a DSL script which I wrote into the icinga2 console, the script works fine.
But when I put the same DSL script into a configuration file, the functions inside for-loops and if statements like for example
get_service("HostName", "checkName").last_check_result.exit_status
do not yield anything. I naively thought that get_service is a predefined global function, and it will work inside my for-loop in the “global scope” even when I load the DSL script via a conf file stored inside /etc/icinga2/zones.d/master

I am not sure whether using “closures” is the right way to get the desired behavior of a function to work within the right “scope”, and if yes, how do I define a closure for a function like get_service when I use it inside my custom global DSL function?
Tried to look through the DSL documentation and such, and it is unclear to me what do I need to do to make such functions work as expected inside my custom DSL script with the same scope like they are running when I execute the DSL script via the icinga2 console.

I would appreciate if someone could nudge me into the right direction.

Or rather, should I give up on trying to write custom DSL scripts (I consider Icinga DSL to be a more elegant solution compared to Python) and rather just write Python3 scripts?
Namely, via Python I can poll the state of the individual checks via API commands, include for-loops, if-statements and the decision making logic into Python, and don’t bother with DSL at all?

Best regards,

1 Like

I’m no expert and only did some minor DSL work but this is interesting stuff and it would be great if you could share some code to make the problem easier understandable.

Below is an example (trying to make the example as simple as possible).
First I connect to my Icinga2 console with the command:
ICINGA2_API_PASSWORD=<MyAPIpassword> icinga2 console --connect 'https://root@localhost:5665/'

If I copy-paste the following DSL script into the console:

// Create a new function which will perform the check coalescing multiple checks into one.
// Define a new global function
globals.MyFunction = function () {
// Set the hostname for the server on which the checks should pass
HostNameToCheck = "MyHostName"

  // List of checks which should pass in a stack
  var listofchecks = [ "ping4" ]
  // Loop over the list of checks
  for (var mycheck in listofchecks ) {
    MyResult = (get_service(HostNameToCheck, mycheck).last_check_result.exit_status)
    return MyResult

and after this, I call the function from the icinga2 console, it works fine:

<5> => MyFunction()

However, if I save the same DSL script into a conf file, and try to call the DSL script from an other conf file like for example:

apply Service "DSL_Test" {
  display_name = "Minimal StackCheck from DSL"
  vars.dummy_state = 3
  vars.dummy_text = MyFunction()
  assign where == "icinga"
  check_command = "dummy"
  check_interval = 5m
  retry_interval = 3m

after restarting the icinga2 service, in the output of the check there will be nothing present, wheres I would expect it to show 0.000000 in the Plugin Output line. Thus, the “scope” of the get_service function is not set as it should when I place it inside a conf file, and I am not sure how to properly use the existing DSL library functions in the right scope. If one needs to set “closure” to these functions when used in a conf file, how to do that, so the function behaves the same like when it runs inside the icinga2 console.

Of course, if I try to use the return value of the get_service function as is now to make some decisions in my custom DSL function loaded from the conf file, my custom DSL function will return the wrong result, since it got nothing back from get_service.

Maybe it’s running but to early and only at creation of the service. What happens if you call it in a CheckCommand attached to the service?

I tried that, and after restarting icinga2.service and look at the Custom Variables,
the value of dummy_text is still empty string.

What happens if you add a log line? If in the service I would expect it to show up once and in the CheckCommand I would expect it to show up every time the check runs.