Monitoring multiple services with same values - a for in a for loop

Hi,

lets say I have multiple db services running on multiple hosts. Each db on each host has slightly different options.

host1 -> db1, db2, db3
db1 -> namespace 1, namespace 2
db2 -> namespace 3, namespace 4

Now, I want to have something like

host1.conf:
vars.db = db1 => “namespace1”, “namespace2”, db2 => “namespace 3”, “namespace4”

service.conf:
apply Service for (namespace => config in host.vars.db)

AND NOW THE MAGIC -> two for loops nested.

Any idea how to do that?

I had the same problem which @dnsmichi solved for me about two years ago, this is the anonymized version of his code.

object Host "mssql-server" {
	check_command = "dummy"
        vars.mssql.instances = {
                "instance1" = {
                        databases = [ "database1-1" ]
                        connected_users = {
                                warning = "1800"
                                critical = "2500"
                        }
                }
                "instance2" = {
                        databases = [ "database2-1", "database2-2", "database2-3", "database2-4" ]
                }
                "instance3" = {
                        databases = [ "database3-1" ]
                        connected_users = {
                                warning = "200"
                                critical = "500"
                        }
                }
                "instance4" = {
                        databases = [ "database4-1" ]
                }
        }
}


globals.get_database_details = function(host, instances) {

  //an algorithm is required which flattens and reverses the dictonary, so we get a unique key in format "instance-database"

  if (instances && typeof(instances) != Dictionary) {
    log(LogWarning, "config", "'instances' is not a Dictionary for '" + host.name + "'.")
    return {} //and log an error
  }

  var res = {}

  for (instance_name => instance_details in instances) {
    //instance_details is a dictionary with 'databases' and so on as keys

    if (instance_details.contains("databases")) {
      for (db_name in instance_details.databases) {
        var key = instance_name + "-" + db_name

        var val = {
          "instance_name" = instance_name
          "db_name" = db_name
        }

        res[key] = val
      }
    }
  }

  //print for debugging
  log(LogInformation, "config/host/" + host.name, Json.encode(res))

  //could be easier if we can assume instance_name and db_name do not contain dashes, then the key could be returned as array and split in the apply with String#split

  return res
}

//send 'host' to the Funktion for better debugging
apply Service "mssql-" for (instance_db => db_details in get_database_details(host, host.vars.mssql.instances)) {
  check_command = "dummy"

  //structur see above
  var database_name = db_details.db_name
  var instance_name = db_details.instance_name

  display_name = "mssql-" + instance_name + "-" + database_name
  vars.mssql_health_server = instance_name
  vars.mssql_health_database = database_name
}
2 Likes

wow… thank you. I’ll need some time to understand whats going on there.

:smiley: It needed several hours for him to write it, another one for me to understand and another to explain to and implement at my customer. So just give it a try, with the debug output it is understandable, but of course it is not so easy.

1 Like