]> granicus.if.org Git - icinga2/commitdiff
Livestatus: Add 'cv_is_json' and encode CV arrays/dicts as json
authorMichael Friedrich <michael.friedrich@netways.de>
Tue, 4 Nov 2014 15:44:45 +0000 (16:44 +0100)
committerMichael Friedrich <michael.friedrich@netways.de>
Tue, 4 Nov 2014 16:39:28 +0000 (17:39 +0100)
refs #7560

doc/9-appendix.md
lib/icinga/compatutility.cpp
lib/livestatus/contactstable.cpp
lib/livestatus/contactstable.hpp
lib/livestatus/hoststable.cpp
lib/livestatus/hoststable.hpp
lib/livestatus/servicestable.cpp
lib/livestatus/servicestable.hpp
test/livestatus/queries/host/customvar
test/livestatus/queries/service/customvar
test/livestatus/run_queries

index cfdc7cbeffe6869fed1b50e09c6583a3f3bbcc0b..d00ece34a75e97ca7f84b2554005e04a8580450a 100644 (file)
@@ -212,6 +212,9 @@ New columns:
   ----------|--------------
   hosts     | is_reachable
   services  | is_reachable
+  hosts            | cv_is_json
+  services  | cv_is_json
+  contacts  | cv_is_json
   hosts     | check_source
   services  | check_source
   downtimes | triggers
index bb2ab7570e2d0cae4554cb9e86985c0c2aa1ed4b..2a699893eca67c2f5d1d2ae660ffec435e1eab2d 100644 (file)
@@ -126,7 +126,7 @@ String CompatUtility::GetCheckableCommandArgs(const Checkable::Ptr& checkable)
                Dictionary::Ptr command_vars = command->GetVars();
 
                if (command_vars) {
-                       BOOST_FOREACH(Dictionary::Pair kv, command_vars) {
+                       BOOST_FOREACH(const Dictionary::Pair& kv, command_vars) {
                                String macro = "$" + kv.first + "$"; // this is too simple
                                if (command_line.Contains(macro))
                                        args->Set(kv.first, kv.second);
@@ -137,7 +137,7 @@ String CompatUtility::GetCheckableCommandArgs(const Checkable::Ptr& checkable)
                Dictionary::Ptr host_vars = host->GetVars();
 
                if (host_vars) {
-                       BOOST_FOREACH(Dictionary::Pair kv, host_vars) {
+                       BOOST_FOREACH(const Dictionary::Pair& kv, host_vars) {
                                String macro = "$" + kv.first + "$"; // this is too simple
                                if (command_line.Contains(macro))
                                        args->Set(kv.first, kv.second);
@@ -151,7 +151,7 @@ String CompatUtility::GetCheckableCommandArgs(const Checkable::Ptr& checkable)
                        Dictionary::Ptr service_vars = service->GetVars();
 
                        if (service_vars) {
-                               BOOST_FOREACH(Dictionary::Pair kv, service_vars) {
+                               BOOST_FOREACH(const Dictionary::Pair& kv, service_vars) {
                                        String macro = "$" + kv.first + "$"; // this is too simple
                                        if (command_line.Contains(macro))
                                                args->Set(kv.first, kv.second);
@@ -163,7 +163,7 @@ String CompatUtility::GetCheckableCommandArgs(const Checkable::Ptr& checkable)
                }
 
                String arg_string;
-               BOOST_FOREACH(Dictionary::Pair kv, args) {
+               BOOST_FOREACH(const Dictionary::Pair& kv, args) {
                        arg_string += Convert::ToString(kv.first) + "=" + Convert::ToString(kv.second) + "!";
                }
                return arg_string;
@@ -388,12 +388,15 @@ Dictionary::Ptr CompatUtility::GetCustomAttributeConfig(const CustomVarObject::P
        if (!vars)
                return Dictionary::Ptr();
 
+       String key;
+       Value value;
+
        ObjectLock olock(vars);
        BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
-               if (!kv.first.IsEmpty()) {
-                       if (!IsLegacyAttribute(object, kv.first))
-                               varsvars->Set(kv.first, kv.second);
-               }
+               if (kv.first.IsEmpty() || IsLegacyAttribute(object, kv.first))
+                       continue;
+
+               varsvars->Set(kv.first, kv.second);
        }
 
        return varsvars;
index e62dc50ce16eddef7722edc4d000f4f7e59e5aba..606ce995c2fecba190b84dca803433cacee7f949 100644 (file)
@@ -23,6 +23,7 @@
 #include "icinga/compatutility.hpp"
 #include "base/dynamictype.hpp"
 #include "base/objectlock.hpp"
+#include "base/json.hpp"
 #include "base/utility.hpp"
 #include <boost/foreach.hpp>
 #include <boost/tuple/tuple.hpp>
@@ -53,6 +54,8 @@ void ContactsTable::AddColumns(Table *table, const String& prefix,
        table->AddColumn(prefix + "vars_variables", Column(&ContactsTable::CustomVariablesAccessor, objectAccessor));
        table->AddColumn(prefix + "modified_attributes", Column(&ContactsTable::ModifiedAttributesAccessor, objectAccessor));
        table->AddColumn(prefix + "modified_attributes_list", Column(&ContactsTable::ModifiedAttributesListAccessor, objectAccessor));
+       table->AddColumn(prefix + "cv_is_json", Column(&ContactsTable::CVIsJsonAccessor, objectAccessor));
+
 }
 
 String ContactsTable::GetName(void) const
@@ -200,7 +203,12 @@ Value ContactsTable::CustomVariableNamesAccessor(const Value& row)
        if (!user)
                return Empty;
 
-       Dictionary::Ptr vars = user->GetVars();
+       Dictionary::Ptr vars;
+
+       {
+               ObjectLock olock(user);
+               vars = CompatUtility::GetCustomAttributeConfig(user);
+       }
 
        if (!vars)
                return Empty;
@@ -208,10 +216,8 @@ Value ContactsTable::CustomVariableNamesAccessor(const Value& row)
        Array::Ptr cv = make_shared<Array>();
 
        ObjectLock olock(vars);
-       String key;
-       Value value;
-       BOOST_FOREACH(boost::tie(key, value), vars) {
-               cv->Add(key);
+       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+               cv->Add(kv.first);
        }
 
        return cv;
@@ -224,7 +230,12 @@ Value ContactsTable::CustomVariableValuesAccessor(const Value& row)
        if (!user)
                return Empty;
 
-       Dictionary::Ptr vars = user->GetVars();
+       Dictionary::Ptr vars;
+
+       {
+               ObjectLock olock(user);
+               vars = CompatUtility::GetCustomAttributeConfig(user);
+       }
 
        if (!vars)
                return Empty;
@@ -232,10 +243,11 @@ Value ContactsTable::CustomVariableValuesAccessor(const Value& row)
        Array::Ptr cv = make_shared<Array>();
 
        ObjectLock olock(vars);
-       String key;
-       Value value;
-       BOOST_FOREACH(boost::tie(key, value), vars) {
-               cv->Add(value);
+       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+               if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
+                       cv->Add(JsonEncode(kv.second));
+               else
+                       cv->Add(kv.second);
        }
 
        return cv;
@@ -248,7 +260,12 @@ Value ContactsTable::CustomVariablesAccessor(const Value& row)
        if (!user)
                return Empty;
 
-       Dictionary::Ptr vars = user->GetVars();
+       Dictionary::Ptr vars;
+
+       {
+               ObjectLock olock(user);
+               vars = CompatUtility::GetCustomAttributeConfig(user);
+       }
 
        if (!vars)
                return Empty;
@@ -256,18 +273,49 @@ Value ContactsTable::CustomVariablesAccessor(const Value& row)
        Array::Ptr cv = make_shared<Array>();
 
        ObjectLock olock(vars);
-       String key;
-       Value value;
-       BOOST_FOREACH(boost::tie(key, value), vars) {
+       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
                Array::Ptr key_val = make_shared<Array>();
-               key_val->Add(key);
-               key_val->Add(value);
+               key_val->Add(kv.first);
+
+               if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
+                       key_val->Add(JsonEncode(kv.second));
+               else
+                       key_val->Add(kv.second);
+
                cv->Add(key_val);
        }
 
        return cv;
 }
 
+Value ContactsTable::CVIsJsonAccessor(const Value& row)
+{
+       User::Ptr user = static_cast<User::Ptr>(row);
+
+       if (!user)
+               return Empty;
+
+       Dictionary::Ptr vars;
+
+       {
+               ObjectLock olock(user);
+               vars = CompatUtility::GetCustomAttributeConfig(user);
+       }
+
+       if (!vars)
+               return Empty;
+
+       bool cv_is_json = false;
+
+       ObjectLock olock(vars);
+       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+               if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
+                       cv_is_json = true;
+       }
+
+       return cv_is_json;
+}
+
 Value ContactsTable::ModifiedAttributesAccessor(const Value& row)
 {
        User::Ptr user = static_cast<User::Ptr>(row);
index e8997bc0fd1b8d9bf1c802cf9c56a5a091cd427b..3f9084efbb879b7af8889ec6bf78866ceafe73e7 100644 (file)
@@ -61,6 +61,7 @@ protected:
        static Value CustomVariablesAccessor(const Value& row);
        static Value ModifiedAttributesAccessor(const Value& row);
        static Value ModifiedAttributesListAccessor(const Value& row);
+       static Value CVIsJsonAccessor(const Value& row);
 };
 
 }
index 1359d33880bc2aea551355cb411971527ffebc37..36c9a4b0c29702a948c1cd6f16281287ea46fec0 100644 (file)
@@ -28,6 +28,7 @@
 #include "icinga/compatutility.hpp"
 #include "base/dynamictype.hpp"
 #include "base/objectlock.hpp"
+#include "base/json.hpp"
 #include "base/convert.hpp"
 #include "base/utility.hpp"
 #include <boost/algorithm/string/classification.hpp>
@@ -160,6 +161,7 @@ void HostsTable::AddColumns(Table *table, const String& prefix,
        table->AddColumn(prefix + "services_with_info", Column(&HostsTable::ServicesWithInfoAccessor, objectAccessor));
        table->AddColumn(prefix + "check_source", Column(&HostsTable::CheckSourceAccessor, objectAccessor));
        table->AddColumn(prefix + "is_reachable", Column(&HostsTable::IsReachableAccessor, objectAccessor));
+       table->AddColumn(prefix + "cv_is_json", Column(&HostsTable::CVIsJsonAccessor, objectAccessor));
 }
 
 String HostsTable::GetName(void) const
@@ -1058,10 +1060,9 @@ Value HostsTable::CustomVariableNamesAccessor(const Value& row)
 
        Array::Ptr cv = make_shared<Array>();
 
-       String key;
-       Value value;
-       BOOST_FOREACH(tie(key, value), vars) {
-               cv->Add(key);
+       ObjectLock olock(vars);
+       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+               cv->Add(kv.first);
        }
 
        return cv;
@@ -1086,10 +1087,12 @@ Value HostsTable::CustomVariableValuesAccessor(const Value& row)
 
        Array::Ptr cv = make_shared<Array>();
 
-       String key;
-       Value value;
-       BOOST_FOREACH(tie(key, value), vars) {
-               cv->Add(value);
+       ObjectLock olock(vars);
+       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+               if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
+                       cv->Add(JsonEncode(kv.second));
+               else
+                       cv->Add(kv.second);
        }
 
        return cv;
@@ -1114,18 +1117,50 @@ Value HostsTable::CustomVariablesAccessor(const Value& row)
 
        Array::Ptr cv = make_shared<Array>();
 
-       String key;
-       Value value;
-       BOOST_FOREACH(tie(key, value), vars) {
+       ObjectLock olock(vars);
+       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
                Array::Ptr key_val = make_shared<Array>();
-               key_val->Add(key);
-               key_val->Add(value);
+               key_val->Add(kv.first);
+
+               if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
+                       key_val->Add(JsonEncode(kv.second));
+               else
+                       key_val->Add(kv.second);
+
                cv->Add(key_val);
        }
 
        return cv;
 }
 
+Value HostsTable::CVIsJsonAccessor(const Value& row)
+{
+       Host::Ptr host = static_cast<Host::Ptr>(row);
+
+       if (!host)
+               return Empty;
+
+       Dictionary::Ptr vars;
+
+       {
+               ObjectLock olock(host);
+               vars = CompatUtility::GetCustomAttributeConfig(host);
+       }
+
+       if (!vars)
+               return Empty;
+
+       bool cv_is_json = false;
+
+       ObjectLock olock(vars);
+       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+               if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
+                       cv_is_json = true;
+       }
+
+       return cv_is_json;
+}
+
 Value HostsTable::ParentsAccessor(const Value& row)
 {
        Host::Ptr host = static_cast<Host::Ptr>(row);
index 57f260483948c3b3d8f195ce7fa5b87e82e770d0..d033ad90bd2a3d3218199461babf1f2338c69a32 100644 (file)
@@ -143,6 +143,7 @@ protected:
        static Value ServicesWithInfoAccessor(const Value& row);
        static Value CheckSourceAccessor(const Value& row);
        static Value IsReachableAccessor(const Value& row);
+       static Value CVIsJsonAccessor(const Value& row);
 };
 
 }
index e001784e4271b4fbc760ad738d202d3b80250716..8bffa2b21777a452b16ddd5183b3bbb4df2bad7c 100644 (file)
@@ -29,6 +29,7 @@
 #include "icinga/compatutility.hpp"
 #include "base/dynamictype.hpp"
 #include "base/objectlock.hpp"
+#include "base/json.hpp"
 #include "base/convert.hpp"
 #include "base/utility.hpp"
 #include <boost/foreach.hpp>
@@ -129,6 +130,7 @@ void ServicesTable::AddColumns(Table *table, const String& prefix,
        table->AddColumn(prefix + "contact_groups", Column(&ServicesTable::ContactGroupsAccessor, objectAccessor));
        table->AddColumn(prefix + "check_source", Column(&ServicesTable::CheckSourceAccessor, objectAccessor));
        table->AddColumn(prefix + "is_reachable", Column(&ServicesTable::IsReachableAccessor, objectAccessor));
+       table->AddColumn(prefix + "cv_is_json", Column(&ServicesTable::CVIsJsonAccessor, objectAccessor));
 
        HostsTable::AddColumns(table, "host_", boost::bind(&ServicesTable::HostAccessor, _1, objectAccessor));
 }
@@ -1063,8 +1065,8 @@ Value ServicesTable::CustomVariableNamesAccessor(const Value& row)
        Array::Ptr cv = make_shared<Array>();
 
        ObjectLock olock(vars);
-       BOOST_FOREACH(const Dictionary::Pair kv, vars) {
-               cv->Add(kv.second);
+       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+               cv->Add(kv.first);
        }
 
        return cv;
@@ -1091,7 +1093,10 @@ Value ServicesTable::CustomVariableValuesAccessor(const Value& row)
 
        ObjectLock olock(vars);
        BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
-               cv->Add(kv.second);
+               if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
+                       cv->Add(JsonEncode(kv.second));
+               else
+                       cv->Add(kv.second);
        }
 
        return cv;
@@ -1116,18 +1121,50 @@ Value ServicesTable::CustomVariablesAccessor(const Value& row)
 
        Array::Ptr cv = make_shared<Array>();
 
-       String key;
-       Value value;
-       BOOST_FOREACH(tie(key, value), vars) {
+       ObjectLock olock(vars);
+       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
                Array::Ptr key_val = make_shared<Array>();
-               key_val->Add(key);
-               key_val->Add(value);
+               key_val->Add(kv.first);
+
+               if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
+                       key_val->Add(JsonEncode(kv.second));
+               else
+                       key_val->Add(kv.second);
+
                cv->Add(key_val);
        }
 
        return cv;
 }
 
+Value ServicesTable::CVIsJsonAccessor(const Value& row)
+{
+       Service::Ptr service = static_cast<Service::Ptr>(row);
+
+       if (!service)
+               return Empty;
+
+       Dictionary::Ptr vars;
+
+       {
+               ObjectLock olock(service);
+               vars = CompatUtility::GetCustomAttributeConfig(service);
+       }
+
+       if (!vars)
+               return Empty;
+
+       bool cv_is_json = false;
+
+       ObjectLock olock(vars);
+       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+               if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
+                       cv_is_json = true;
+       }
+
+       return cv_is_json;
+}
+
 Value ServicesTable::GroupsAccessor(const Value& row)
 {
        Service::Ptr service = static_cast<Service::Ptr>(row);
index 8446a58194153c7dce5b96aac012691e314adbd5..7b7e037e9588775ad709e9fc22ba846d8f49dcfd 100644 (file)
@@ -126,6 +126,7 @@ protected:
        static Value ContactGroupsAccessor(const Value& row);
        static Value CheckSourceAccessor(const Value& row);
        static Value IsReachableAccessor(const Value& row);
+       static Value CVIsJsonAccessor(const Value& row);
 };
 
 }
index b98ff3c542b0b201664cac3487e79878669645be..57f2e00123cc44ad564b5be05002f5d462dd80c8 100644 (file)
@@ -1,4 +1,4 @@
-GET hosts 
-Columns: custom_variable_names custom_variable_values custom_variables
+GET hosts
+Columns: name custom_variable_names custom_variable_values custom_variables cv_is_json
 ResponseHeader: fixed16
 
index 8f52f27a79993ad61446b71e72b7033ce4e07690..75c452ca45fcb8645c644b9d2c6fd43812b70519 100644 (file)
@@ -1,4 +1,4 @@
 GET services
-Columns: custom_variable_names custom_variable_values custom_variables 
+Columns: host_name service_description custom_variables cv_is_json
 ResponseHeader: fixed16
 
index d137c3c521d216dad85f5699625b0c27b2530e6d..63448c8ce877304b2e286a5091b10f1db6f5dacb 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+NC=`which nc`
+LIVESTATUSSOCKET="/var/run/icinga2/cmd/livestatus"
 LIVESTATUSHOST="127.0.0.1"
 LIVESTATUSPORT="6558"
 LIVESTATUSQUERIES="./queries"
@@ -8,14 +10,14 @@ LIVESTATUSTABLE=$1
 
 if [ -n "$LIVESTATUSTABLE" ]; then
        cat "$LIVESTATUSTABLE"
-       (cat "$LIVESTATUSTABLE"; sleep 1) | netcat $LIVESTATUSHOST $LIVESTATUSPORT
+       (cat "$LIVESTATUSTABLE"; sleep 1) | $NC -U $LIVESTATUSSOCKET
 else
 
        echo -e "Looking into $LIVESTATUSQUERIES\n"
        for q in $(find $LIVESTATUSQUERIES -type f)
        do
                cat $q
-               (cat $q; sleep 1) | netcat $LIVESTATUSHOST $LIVESTATUSPORT
+               (cat $q; sleep 1) | $NC -U $LIVESTATUSSOCKET
                echo -e "================================\n\n"
        done
 fi