diff --git a/doc/1-about.md b/doc/1-about.md index 60672868b..22d4dcf8d 100644 --- a/doc/1-about.md +++ b/doc/1-about.md @@ -62,6 +62,8 @@ Icinga 2 is available as [Vagrant Demo VM](#vagrant). * DB IDO schema update to version `1.12.0` * schema files in `lib/db_ido_{mysql,pgsql}/schema` (source) + * Table `programstatus`: New column `program_version` + * Table `customvariables` and `customvariablestatus`: New column `is_json` (required for custom attribute array/dictionary support) * New CLI commands #7245 * `icinga2 feature {enable,disable}` replaces `icinga2-{enable,disable}-feature` script #7250 * `icinga2 object list` replaces `icinga2-list-objects` script #7251 diff --git a/doc/9-appendix.md b/doc/9-appendix.md index 1552867e2..cfdc7cbef 100644 --- a/doc/9-appendix.md +++ b/doc/9-appendix.md @@ -186,6 +186,7 @@ New columns: {host,service}group | notes | TEXT | NULL | - {host,service}group | notes_url | TEXT | NULL | - {host,service}group | action_url | TEXT | NULL | - + customvariable* | is_json | integer | 0 | Defines whether `varvalue` is a json encoded string from custom attributes, or not Additional command custom variables populated from 'vars' dictionary. Additional global custom variables populated from 'Vars' constant (object_id is NULL). @@ -654,5 +655,3 @@ Not supported: `neb_callbacks`, `neb_callbacks_rate`, `requests`, `requests_rate current_host_ | join | Prefix for attributes from implicit join with hosts table. Not supported: `debug_info`. - - diff --git a/lib/db_ido/dbobject.cpp b/lib/db_ido/dbobject.cpp index 7f3f3c47b..181ac000d 100644 --- a/lib/db_ido/dbobject.cpp +++ b/lib/db_ido/dbobject.cpp @@ -26,6 +26,7 @@ #include "remote/endpoint.hpp" #include "base/dynamicobject.hpp" #include "base/dynamictype.hpp" +#include "base/json.hpp" #include "base/convert.hpp" #include "base/objectlock.hpp" #include "base/utility.hpp" @@ -171,10 +172,12 @@ void DbObject::SendVarsConfigUpdate(void) continue; String value; + int is_json = 0; - if (kv.second.IsObjectType()) - value = Utility::Join(kv.second, ';'); - else + if (kv.second.IsObjectType() || kv.second.IsObjectType()) { + value = JsonEncode(kv.second); + is_json = 1; + } else value = kv.second; int overridden = custom_var_object->IsVarOverridden(kv.first) ? 1 : 0; @@ -186,6 +189,7 @@ void DbObject::SendVarsConfigUpdate(void) Dictionary::Ptr fields = make_shared(); fields->Set("varname", kv.first); fields->Set("varvalue", value); + fields->Set("is_json", is_json); fields->Set("config_type", 1); fields->Set("has_been_modified", overridden); fields->Set("object_id", obj); @@ -219,9 +223,18 @@ void DbObject::SendVarsStatusUpdate(void) ObjectLock olock (vars); BOOST_FOREACH(const Dictionary::Pair& kv, vars) { - if (kv.first.IsEmpty() || kv.second.IsObject()) + if (kv.first.IsEmpty()) continue; + String value; + int is_json = 0; + + if (kv.second.IsObjectType() || kv.second.IsObjectType()) { + value = JsonEncode(kv.second); + is_json = 1; + } else + value = kv.second; + int overridden = custom_var_object->IsVarOverridden(kv.first) ? 1 : 0; Log(LogDebug, "DbObject") @@ -229,8 +242,9 @@ void DbObject::SendVarsStatusUpdate(void) << "' overridden: " << overridden; Dictionary::Ptr fields = make_shared(); - fields->Set("varname", Convert::ToString(kv.first)); - fields->Set("varvalue", Convert::ToString(kv.second)); + fields->Set("varname", kv.first); + fields->Set("varvalue", value); + fields->Set("is_json", is_json); fields->Set("has_been_modified", overridden); fields->Set("status_update_time", DbValue::FromTimestamp(Utility::GetTime())); fields->Set("object_id", obj); diff --git a/lib/db_ido/userdbobject.cpp b/lib/db_ido/userdbobject.cpp index 53da290db..4e7027983 100644 --- a/lib/db_ido/userdbobject.cpp +++ b/lib/db_ido/userdbobject.cpp @@ -93,11 +93,12 @@ void UserDbObject::OnConfigUpdate(void) if (vars) { /* This is sparta. */ for (int i = 1; i <= 6; i++) { String key = "address" + Convert::ToString(i); - String val = vars->Get(key); - if (val.IsEmpty()) + if (!vars->Contains(key)) continue; + String val = vars->Get(key); + fields->Set("contact_id", DbValue::FromObjectInsertID(user)); fields->Set("address_number", i); fields->Set("address", val); diff --git a/lib/db_ido_mysql/schema/mysql.sql b/lib/db_ido_mysql/schema/mysql.sql index 52ba3736a..9cbaed26b 100644 --- a/lib/db_ido_mysql/schema/mysql.sql +++ b/lib/db_ido_mysql/schema/mysql.sql @@ -339,6 +339,7 @@ CREATE TABLE IF NOT EXISTS icinga_customvariables ( has_been_modified smallint default 0, varname varchar(255) character set latin1 collate latin1_general_cs default NULL, varvalue TEXT character set latin1 default '', + is_json smallint default 0, PRIMARY KEY (customvariable_id), UNIQUE KEY object_id_2 (object_id,config_type,varname), KEY varname (varname) @@ -358,6 +359,7 @@ CREATE TABLE IF NOT EXISTS icinga_customvariablestatus ( has_been_modified smallint default 0, varname varchar(255) character set latin1 collate latin1_general_cs default NULL, varvalue TEXT character set latin1 default '', + is_json smallint default 0, PRIMARY KEY (customvariablestatus_id), UNIQUE KEY object_id_2 (object_id,varname), KEY varname (varname) diff --git a/lib/db_ido_mysql/schema/upgrade/2.2.0.sql b/lib/db_ido_mysql/schema/upgrade/2.2.0.sql index dd77f77f2..9b4de9c6a 100644 --- a/lib/db_ido_mysql/schema/upgrade/2.2.0.sql +++ b/lib/db_ido_mysql/schema/upgrade/2.2.0.sql @@ -12,6 +12,9 @@ ALTER TABLE `icinga_programstatus` ADD COLUMN `program_version` varchar(64) char ALTER TABLE icinga_contacts MODIFY alias TEXT character set latin1 default ''; ALTER TABLE icinga_hosts MODIFY alias TEXT character set latin1 default ''; +ALTER TABLE icinga_customvariables ADD COLUMN is_json smallint default 0; +ALTER TABLE icinga_customvariablestatus ADD COLUMN is_json smallint default 0; + -- ----------------------------------------- -- update dbversion -- ----------------------------------------- diff --git a/lib/db_ido_pgsql/schema/pgsql.sql b/lib/db_ido_pgsql/schema/pgsql.sql index 8bd0b35fd..6ce044654 100644 --- a/lib/db_ido_pgsql/schema/pgsql.sql +++ b/lib/db_ido_pgsql/schema/pgsql.sql @@ -365,6 +365,7 @@ CREATE TABLE icinga_customvariables ( has_been_modified INTEGER default 0, varname TEXT default '', varvalue TEXT default '', + is_json INTEGER default 0, CONSTRAINT PK_customvariable_id PRIMARY KEY (customvariable_id) , CONSTRAINT UQ_customvariables UNIQUE (object_id,config_type,varname) ) ; @@ -384,6 +385,7 @@ CREATE TABLE icinga_customvariablestatus ( has_been_modified INTEGER default 0, varname TEXT default '', varvalue TEXT default '', + is_json INTEGER default 0, CONSTRAINT PK_customvariablestatus_id PRIMARY KEY (customvariablestatus_id) , CONSTRAINT UQ_customvariablestatus UNIQUE (object_id,varname) ) ; diff --git a/lib/db_ido_pgsql/schema/upgrade/2.2.0.sql b/lib/db_ido_pgsql/schema/upgrade/2.2.0.sql index f27bc5bcf..88350b355 100644 --- a/lib/db_ido_pgsql/schema/upgrade/2.2.0.sql +++ b/lib/db_ido_pgsql/schema/upgrade/2.2.0.sql @@ -9,6 +9,10 @@ ALTER TABLE icinga_programstatus ADD COLUMN program_version TEXT default NULL; +ALTER TABLE icinga_customvariables ADD COLUMN is_json INTEGER default 0; +ALTER TABLE icinga_customvariablestatus ADD COLUMN is_json INTEGER default 0; + + -- ----------------------------------------- -- update dbversion -- ----------------------------------------- diff --git a/test/config/7560.conf b/test/config/7560.conf new file mode 100644 index 000000000..422cc0481 --- /dev/null +++ b/test/config/7560.conf @@ -0,0 +1,41 @@ +object Host "7560-server" { + import "test-generic-host" + address = "127.0.0.1" + check_command = "hostalive" + + vars.interfaces += { + eth0 = { + port = 1 + vlan = "internal" + address = "127.0.0.2" + qos = "enabled" + } + eth1 = { + port = 2 + vlan = "mgmt" + address = "127.0.1.2" + } + eth2 = { + port = 3 + vlan = "remote" + address = "127.0.2.2" + } + } +} + +apply Service "if-" for (if_name => config in host.vars.interfaces) { + import "test-generic-service" + check_command = "ping4" + + vars.qos = "disabled" + vars += config + + display_name = "if-" + if_name + "-" + vars.vlan + + notes = "Interface check for Port " + string(vars.port) + " in VLAN " + vars.vlan + " on Address " + vars.address + " QoS " + vars.qos + notes_url = "http://foreman.company.com/hosts/" + host.name + action_url = "http://snmp.checker.company.com/" + host.name + "if-" + if_name + + assign where match("7560-*", host.name) && typeof(host.vars.interfaces) == typeof({}) +} +