Author: @mfriedrich
Version: v0.1Tested with: Icinga 2 v2.10.5
Question
Custom facts for database would include nested information.
-
- Level: production or staging
-
- Level: db or app name
-
- Level: additional configuration
Example:
vars.mysql_databases["production"] = {
"app1" = {
"port" = 3306
},
"app2" = {
"port" = 3307
}
}
vars.mysql_databases["staging"] = {
"app1" = {
"port" = 3306
},
"app2" = {
"port" = 3307
}
}
Apply for needs 2 levels where the key is a unique name for the service object being generated.
The idea is to flatten the Dictionary to the 2nd level and use a key like this: production-app1
or staging-app2
.
"staging-app1" = {
port = 3306
}
"staging-app7" = {
port = 3307
}
"production-app1" = {
port = 3306
}
"production-app2" = {
port = 3307
}
This can be used to generate service objects and use the inner dictionary as config
, e.g. to set the port for the database instance.
Solution
Sourcing from Icinga 2 DSL Feature: Namespaces coming in v2.10
Function
We’re using a dedicated namespace called MyFunctions
instead of putting the function into the global namespace. These functions are organized in functions.conf
which must be included in icinga2.conf
after the constants.conf
file.
vim /etc/icinga2/icinga2.conf
include "constants.conf"
include "functions.conf"
vim /etc/icinga2/functions.conf
namespace MyFunctions {
/* Flatten a dictionary with unique keys for service apply for rules. */
function flattenDictionary2ndLevel(obj, d) {
var res = {}
// Some sanity checks up front
if (typeof(d) != Dictionary) {
//log(LogWarning, "flattenDictionary2ndLevel", "ERROR: parameter is not a dictionary.")
return {} // return an empty result set on error, including the log above
}
// Loop over the given dictionary
for (k1 => v1 in d) {
// Sanity check
if (typeof(v1) != Dictionary) {
//log(LogWarning, "flattenDictionary2ndLevel", "ERROR: First level with key " + k1 + " is not a dictionary value.")
continue;
}
// Nested loop building the unique flattened key name
for (k2 => v2 in v1) {
var new_key = k1 + "-" + k2 // Generate a unique name.
var new_val = v2.clone()
// Add a specific global constant - optional example.
if (globals.MysqlUsername != "") {
new_val["username"] = globals.MysqlUsername
}
// Store the value with the new key
res[new_key] = new_val
}
}
//log(LogInformation, "flattenDictionary2ndLevel", res)
return res
}
}
Host Object and Apply For
// Load the namespace
using MyFunctions
object Host "db-host01" {
check_command = "dummy"
vars.mysql_databases["production"] = {
"app1" = {
"port" = 3306
},
"app2" = {
"port" = 3307
}
}
vars.mysql_databases["staging"] = {
"app1" = {
"port" = 3306
},
"app2" = {
"port" = 3307
}
}
}
apply Service "mysql-" for (db_key => config in flattenDictionary2ndLevel(host, host.vars.mysql_databases)) {
check_command = "dummy"
vars += config
}
Parameters
Depending on the configuration and used check_command
, port
needs to be renamed to mysql_health_port
in order to make vars += config
work.
Or you’ll configure it manually inside the apply for scope with:
if (config.port) {
vars.mysql_health_port = config.port
}
Object List Verification
michi@mbpmif /usr/local/icinga/icinga2/etc/icinga2 $ icinga2 object list --type Service --name db-host01*
Object 'db-host01!mysql-staging-app2' of type 'Service':
% declared in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* __name = "db-host01!mysql-staging-app2"
* action_url = ""
* check_command = "dummy"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 25:3-25:25
* check_interval = 300
* check_period = ""
* check_timeout = null
* command_endpoint = ""
* display_name = "mysql-staging-app2"
* enable_active_checks = true
* enable_event_handler = true
* enable_flapping = false
* enable_notifications = true
* enable_passive_checks = true
* enable_perfdata = true
* event_command = ""
* flapping_threshold = 0
* flapping_threshold_high = 30
* flapping_threshold_low = 25
* groups = [ ]
* host_name = "db-host01"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* icon_image = ""
* icon_image_alt = ""
* max_check_attempts = 3
* name = "mysql-staging-app2"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* notes = ""
* notes_url = ""
* package = "_etc"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* retry_interval = 60
* source_location
* first_column = 1
* first_line = 24
* last_column = 107
* last_line = 24
* path = "/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf"
* templates = [ "mysql-staging-app2" ]
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* type = "Service"
* vars
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 26:3-26:16
* port = 3307
* volatile = false
* zone = ""
Object 'db-host01!mysql-staging-app1' of type 'Service':
% declared in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* __name = "db-host01!mysql-staging-app1"
* action_url = ""
* check_command = "dummy"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 25:3-25:25
* check_interval = 300
* check_period = ""
* check_timeout = null
* command_endpoint = ""
* display_name = "mysql-staging-app1"
* enable_active_checks = true
* enable_event_handler = true
* enable_flapping = false
* enable_notifications = true
* enable_passive_checks = true
* enable_perfdata = true
* event_command = ""
* flapping_threshold = 0
* flapping_threshold_high = 30
* flapping_threshold_low = 25
* groups = [ ]
* host_name = "db-host01"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* icon_image = ""
* icon_image_alt = ""
* max_check_attempts = 3
* name = "mysql-staging-app1"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* notes = ""
* notes_url = ""
* package = "_etc"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* retry_interval = 60
* source_location
* first_column = 1
* first_line = 24
* last_column = 107
* last_line = 24
* path = "/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf"
* templates = [ "mysql-staging-app1" ]
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* type = "Service"
* vars
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 26:3-26:16
* port = 3306
* volatile = false
* zone = ""
Object 'db-host01!mysql-production-app2' of type 'Service':
% declared in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* __name = "db-host01!mysql-production-app2"
* action_url = ""
* check_command = "dummy"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 25:3-25:25
* check_interval = 300
* check_period = ""
* check_timeout = null
* command_endpoint = ""
* display_name = "mysql-production-app2"
* enable_active_checks = true
* enable_event_handler = true
* enable_flapping = false
* enable_notifications = true
* enable_passive_checks = true
* enable_perfdata = true
* event_command = ""
* flapping_threshold = 0
* flapping_threshold_high = 30
* flapping_threshold_low = 25
* groups = [ ]
* host_name = "db-host01"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* icon_image = ""
* icon_image_alt = ""
* max_check_attempts = 3
* name = "mysql-production-app2"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* notes = ""
* notes_url = ""
* package = "_etc"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* retry_interval = 60
* source_location
* first_column = 1
* first_line = 24
* last_column = 107
* last_line = 24
* path = "/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf"
* templates = [ "mysql-production-app2" ]
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* type = "Service"
* vars
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 26:3-26:16
* port = 3307
* volatile = false
* zone = ""
Object 'db-host01!mysql-production-app1' of type 'Service':
% declared in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* __name = "db-host01!mysql-production-app1"
* action_url = ""
* check_command = "dummy"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 25:3-25:25
* check_interval = 300
* check_period = ""
* check_timeout = null
* command_endpoint = ""
* display_name = "mysql-production-app1"
* enable_active_checks = true
* enable_event_handler = true
* enable_flapping = false
* enable_notifications = true
* enable_passive_checks = true
* enable_perfdata = true
* event_command = ""
* flapping_threshold = 0
* flapping_threshold_high = 30
* flapping_threshold_low = 25
* groups = [ ]
* host_name = "db-host01"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* icon_image = ""
* icon_image_alt = ""
* max_check_attempts = 3
* name = "mysql-production-app1"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* notes = ""
* notes_url = ""
* package = "_etc"
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* retry_interval = 60
* source_location
* first_column = 1
* first_line = 24
* last_column = 107
* last_line = 24
* path = "/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf"
* templates = [ "mysql-production-app1" ]
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 24:1-24:107
* type = "Service"
* vars
% = modified in '/usr/local/icinga/icinga2/etc/icinga2/tests/flatten.conf', lines 26:3-26:16
* port = 3306
* volatile = false
* zone = ""