]> granicus.if.org Git - icinga2/commitdiff
Refactor the config validator so that it doesn't require serialized objects
authorGunnar Beutner <gunnar.beutner@netways.de>
Thu, 20 Nov 2014 12:28:21 +0000 (13:28 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Thu, 20 Nov 2014 12:28:21 +0000 (13:28 +0100)
refs #7701

16 files changed:
lib/compat/compatlogger.cpp
lib/compat/compatlogger.hpp
lib/config/base-type.conf
lib/config/configitem.cpp
lib/config/configtype.cpp
lib/config/configtype.hpp
lib/db_ido/dbconnection.cpp
lib/db_ido/dbconnection.hpp
lib/icinga/command.cpp
lib/icinga/command.hpp
lib/icinga/dependency.cpp
lib/icinga/dependency.hpp
lib/icinga/notification.cpp
lib/icinga/notification.hpp
lib/livestatus/livestatuslistener.cpp
lib/livestatus/livestatuslistener.hpp

index 1c3a3f0769c160868deb8682bc939e09fd0259e6..01e479d4850ac0fb2307869c9b3a2ac5000ded9a 100644 (file)
@@ -563,11 +563,11 @@ void CompatLogger::RotationTimerHandler(void)
        ScheduleNextRotation();
 }
 
-void CompatLogger::ValidateRotationMethod(const String& location, const Dictionary::Ptr& attrs)
+void CompatLogger::ValidateRotationMethod(const String& location, const CompatLogger::Ptr& object)
 {
-       Value rotation_method = attrs->Get("rotation_method");
+       String rotation_method = object->GetRotationMethod();
 
-       if (!rotation_method.IsEmpty() && rotation_method != "HOURLY" && rotation_method != "DAILY" &&
+       if (rotation_method != "HOURLY" && rotation_method != "DAILY" &&
            rotation_method != "WEEKLY" && rotation_method != "MONTHLY" && rotation_method != "NONE") {
                ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
                    location + ": Rotation method '" + rotation_method + "' is invalid.");
index 82f5c36eabd1bc66a76e723caeea8e68f3562444..5c75934f09ccd32421f0f361814f7b8d3e225fc5 100644 (file)
@@ -41,7 +41,7 @@ public:
 
        static Value StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
 
-       static void ValidateRotationMethod(const String& location, const Dictionary::Ptr& attrs);
+       static void ValidateRotationMethod(const String& location, const CompatLogger::Ptr& object);
 
 protected:
        virtual void Start(void);
index 542026eec79eeaa1959175718c76c4c9467a1cfc..a45329d9b4c5e83fa99d47144952ece912f8b18b 100644 (file)
@@ -21,6 +21,8 @@
        %require "__name",
        %attribute %string "__name",
 
+       %attribute %string "name",
+
        %require "type",
        %attribute %string "type",
 
index 0b48c8a814b3d80c938576da60e4fc5f0ef14700..00beca8bf8e551ae8a9132b7a87fb4a695646495 100644 (file)
@@ -209,8 +209,7 @@ DynamicObject::Ptr ConfigItem::Commit(bool discard)
                TypeRuleUtilities utils;
 
                try {
-                       attrs->Remove("name");
-                       ctype->ValidateItem(GetName(), attrs, GetDebugInfo(), &utils);
+                       ctype->ValidateItem(GetName(), dobj, GetDebugInfo(), &utils);
                } catch (const ConfigError& ex) {
                        const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
                        ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
index 9970a440c44a89f382fca876c1666cd2e67198b1..9a5873339dd4596d6dfd63b815868deaba19a431 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "config/configtype.hpp"
 #include "config/configcompilercontext.hpp"
+#include "config/expression.hpp"
 #include "base/objectlock.hpp"
 #include "base/convert.hpp"
 #include "base/singleton.hpp"
@@ -72,7 +73,7 @@ void ConfigType::AddParentRules(std::vector<TypeRuleList::Ptr>& ruleLists, const
        }
 }
 
-void ConfigType::ValidateItem(const String& name, const Dictionary::Ptr& attrs, const DebugInfo& debugInfo, const TypeRuleUtilities *utils)
+void ConfigType::ValidateItem(const String& name, const Object::Ptr& object, const DebugInfo& debugInfo, const TypeRuleUtilities *utils)
 {
        String location = "Object '" + name + "' (Type: '" + GetName() + "')";
 
@@ -86,7 +87,7 @@ void ConfigType::ValidateItem(const String& name, const Dictionary::Ptr& attrs,
        AddParentRules(ruleLists, this);
        ruleLists.push_back(m_RuleList);
 
-       ValidateDictionary(attrs, ruleLists, locations, utils);
+       ValidateObject(object, ruleLists, locations, utils);
 }
 
 String ConfigType::LocationToString(const std::vector<String>& locations)
@@ -105,7 +106,55 @@ String ConfigType::LocationToString(const std::vector<String>& locations)
        return stack;
 }
 
-void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary,
+void ConfigType::ValidateAttribute(const String& key, const Value& value,
+    const std::vector<TypeRuleList::Ptr>& ruleLists, std::vector<String>& locations,
+    const TypeRuleUtilities *utils)
+{
+       TypeValidationResult overallResult = ValidationUnknownField;
+       std::vector<TypeRuleList::Ptr> subRuleLists;
+       String hint;
+
+       locations.push_back("Key " + key);
+
+       BOOST_FOREACH(const TypeRuleList::Ptr& ruleList, ruleLists) {
+               TypeRuleList::Ptr subRuleList;
+               TypeValidationResult result = ruleList->ValidateAttribute(key, value, &subRuleList, &hint, utils);
+
+               if (subRuleList)
+                       subRuleLists.push_back(subRuleList);
+
+               if (overallResult == ValidationOK)
+                       continue;
+
+               if (result == ValidationOK) {
+                       overallResult = result;
+                       continue;
+               }
+
+               if (result == ValidationInvalidType)
+                       overallResult = result;
+       }
+
+       if (overallResult == ValidationUnknownField)
+               ConfigCompilerContext::GetInstance()->AddMessage(true, "Unknown attribute: " + LocationToString(locations));
+       else if (overallResult == ValidationInvalidType) {
+               String message = "Invalid value: " + LocationToString(locations);
+
+               if (!hint.IsEmpty())
+                       message += ": " + hint;
+
+               ConfigCompilerContext::GetInstance()->AddMessage(true, message);
+       }
+
+       if (!subRuleLists.empty() && value.IsObject() && !value.IsObjectType<Array>())
+               ValidateObject(value, subRuleLists, locations, utils);
+       else if (!subRuleLists.empty() && value.IsObjectType<Array>())
+               ValidateArray(value, subRuleLists, locations, utils);
+
+       locations.pop_back();
+}
+
+void ConfigType::ValidateObject(const Object::Ptr& object,
     const std::vector<TypeRuleList::Ptr>& ruleLists, std::vector<String>& locations,
     const TypeRuleUtilities *utils)
 {
@@ -113,7 +162,7 @@ void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary,
                BOOST_FOREACH(const String& require, ruleList->GetRequires()) {
                        locations.push_back("Attribute '" + require + "'");
 
-                       Value value = dictionary->Get(require);
+                       Value value = Expression::GetField(object, require);
 
                        if (value.IsEmpty() || (value.IsString() && static_cast<String>(value).IsEmpty())) {
                                ConfigCompilerContext::GetInstance()->AddMessage(true,
@@ -133,57 +182,34 @@ void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary,
 
                        std::vector<Value> arguments;
                        arguments.push_back(LocationToString(locations));
-                       arguments.push_back(dictionary);
+                       arguments.push_back(object);
 
                        func->Invoke(arguments);
                }
        }
 
-       ObjectLock olock(dictionary);
+       Dictionary::Ptr dictionary = dynamic_pointer_cast<Dictionary>(object);
 
-       BOOST_FOREACH(const Dictionary::Pair& kv, dictionary) {
-               TypeValidationResult overallResult = ValidationUnknownField;
-               std::vector<TypeRuleList::Ptr> subRuleLists;
-               String hint;
+       if (dictionary) {
+               ObjectLock olock(dictionary);
 
-               locations.push_back("Attribute '" + kv.first + "'");
+               BOOST_FOREACH(const Dictionary::Pair& kv, dictionary) {
+                       ValidateAttribute(kv.first, kv.second, ruleLists, locations, utils);
+               }
+       } else {
+               Type::Ptr type = object->GetReflectionType();
 
-               BOOST_FOREACH(const TypeRuleList::Ptr& ruleList, ruleLists) {
-                       TypeRuleList::Ptr subRuleList;
-                       TypeValidationResult result = ruleList->ValidateAttribute(kv.first, kv.second, &subRuleList, &hint, utils);
+               if (!type)
+                       return;
 
-                       if (subRuleList)
-                               subRuleLists.push_back(subRuleList);
+               for (int i = 0; i < type->GetFieldCount(); i++) {
+                       Field field = type->GetFieldInfo(i);
 
-                       if (overallResult == ValidationOK)
+                       if (!(field.Attributes & FAConfig))
                                continue;
 
-                       if (result == ValidationOK) {
-                               overallResult = result;
-                               continue;
-                       }
-
-                       if (result == ValidationInvalidType)
-                               overallResult = result;
-               }
-
-               if (overallResult == ValidationUnknownField)
-                       ConfigCompilerContext::GetInstance()->AddMessage(true, "Unknown attribute: " + LocationToString(locations));
-               else if (overallResult == ValidationInvalidType) {
-                       String message = "Invalid value for attribute: " + LocationToString(locations);
-
-                       if (!hint.IsEmpty())
-                               message += ": " + hint;
-
-                       ConfigCompilerContext::GetInstance()->AddMessage(true, message);
+                       ValidateAttribute(field.Name, object->GetField(i), ruleLists, locations, utils);
                }
-
-               if (!subRuleLists.empty() && kv.second.IsObjectType<Dictionary>())
-                       ValidateDictionary(kv.second, subRuleLists, locations, utils);
-               else if (!subRuleLists.empty() && kv.second.IsObjectType<Array>())
-                       ValidateArray(kv.second, subRuleLists, locations, utils);
-
-               locations.pop_back();
        }
 }
 
@@ -229,48 +255,7 @@ void ConfigType::ValidateArray(const Array::Ptr& array,
                key = Convert::ToString(index);
                index++;
 
-               TypeValidationResult overallResult = ValidationUnknownField;
-               std::vector<TypeRuleList::Ptr> subRuleLists;
-               String hint;
-
-               locations.push_back("Index " + key);
-
-               BOOST_FOREACH(const TypeRuleList::Ptr& ruleList, ruleLists) {
-                       TypeRuleList::Ptr subRuleList;
-                       TypeValidationResult result = ruleList->ValidateAttribute(key, value, &subRuleList, &hint, utils);
-
-                       if (subRuleList)
-                               subRuleLists.push_back(subRuleList);
-
-                       if (overallResult == ValidationOK)
-                               continue;
-
-                       if (result == ValidationOK) {
-                               overallResult = result;
-                               continue;
-                       }
-
-                       if (result == ValidationInvalidType)
-                               overallResult = result;
-               }
-
-               if (overallResult == ValidationUnknownField)
-                       ConfigCompilerContext::GetInstance()->AddMessage(true, "Unknown attribute: " + LocationToString(locations));
-               else if (overallResult == ValidationInvalidType) {
-                       String message = "Invalid value for array index: " + LocationToString(locations);
-
-                       if (!hint.IsEmpty())
-                               message += ": " + hint;
-
-                       ConfigCompilerContext::GetInstance()->AddMessage(true, message);
-               }
-
-               if (!subRuleLists.empty() && value.IsObjectType<Dictionary>())
-                       ValidateDictionary(value, subRuleLists, locations, utils);
-               else if (!subRuleLists.empty() && value.IsObjectType<Array>())
-                       ValidateArray(value, subRuleLists, locations, utils);
-
-               locations.pop_back();
+               ValidateAttribute(key, value, ruleLists, locations, utils);
        }
 }
 
index aa8b770adf4dc8ef438bfabf0f7b041072f2b36b..b2dd527eb39e3c492689334f466537c78559ed17 100644 (file)
@@ -50,7 +50,7 @@ public:
 \r
        DebugInfo GetDebugInfo(void) const;\r
 \r
-       void ValidateItem(const String& name, const Dictionary::Ptr& attrs,\r
+       void ValidateItem(const String& name, const Object::Ptr& object,\r
            const DebugInfo& debugInfo, const TypeRuleUtilities *utils);\r
 \r
        void Register(void);\r
@@ -65,7 +65,10 @@ private:
        TypeRuleList::Ptr m_RuleList;\r
        DebugInfo m_DebugInfo; /**< Debug information. */\r
 \r
-       static void ValidateDictionary(const Dictionary::Ptr& dictionary,\r
+       static void ValidateAttribute(const String& key, const Value& value,\r
+           const std::vector<TypeRuleList::Ptr>& ruleLists, std::vector<String>& locations,\r
+           const TypeRuleUtilities *utils);\r
+       static void ValidateObject(const Object::Ptr& object,\r
            const std::vector<TypeRuleList::Ptr>& ruleLists, std::vector<String>& locations,\r
            const TypeRuleUtilities *utils);\r
        static void ValidateArray(const Array::Ptr& array,\r
index e8c2e1435abc64bb424410028c29f081e1a8bbaf..d754505f20becc995f75efa28cd532c3f6121607 100644 (file)
@@ -421,12 +421,9 @@ void DbConnection::PrepareDatabase(void)
        }
 }
 
-void DbConnection::ValidateFailoverTimeout(const String& location, const Dictionary::Ptr& attrs)
+void DbConnection::ValidateFailoverTimeout(const String& location, const DbConnection::Ptr& object)
 {
-       if (!attrs->Contains("failover_timeout"))
-               return;
-
-       if (attrs->Get("failover_timeout") < 60) {
+       if (object->GetFailoverTimeout() < 60) {
                ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
                    location + ": Failover timeout minimum is 60s.");
        }
index cac7f210d4a84261909544054b3d9507a42235d5..befe2fc610f966a8ecd3f862f2b7ed6ebf614b5d 100644 (file)
@@ -63,7 +63,7 @@ public:
        void SetStatusUpdate(const DbObject::Ptr& dbobj, bool hasupdate);
        bool GetStatusUpdate(const DbObject::Ptr& dbobj) const;
 
-       static void ValidateFailoverTimeout(const String& location, const Dictionary::Ptr& attrs);
+       static void ValidateFailoverTimeout(const String& location, const DbConnection::Ptr& object);
 
 protected:
        virtual void OnConfigLoaded(void);
index 4056c90377ac2c745abb563bb5d96c79843f3a93..947fcf3b8e4b31b39eb3202554d15325341be9d7 100644 (file)
@@ -44,9 +44,9 @@ void Command::SetModifiedAttributes(int flags, const MessageOrigin& origin)
        }
 }
 
-void Command::ValidateAttributes(const String& location, const Dictionary::Ptr& attrs)
+void Command::ValidateAttributes(const String& location, const Command::Ptr& object)
 {
-       if (attrs->Get("arguments") != Empty && !attrs->Get("command").IsObjectType<Array>()) {
+       if (object->GetArguments() != Empty && !object->GetCommandLine().IsObjectType<Array>()) {
                ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
                    location + ": Attribute 'command' must be an array if the 'arguments' attribute is set.");
        }
index ad21659b2f52666fa3e3c4c1b37be2f8aefc454a..5bb38bed5a1a9885ac72a67855a30894d51fddd9 100644 (file)
@@ -39,7 +39,7 @@ public:
 
        //virtual Dictionary::Ptr Execute(const Object::Ptr& context) = 0;
 
-       static void ValidateAttributes(const String& location, const Dictionary::Ptr& attrs);
+       static void ValidateAttributes(const String& location, const Command::Ptr& object);
 
        int GetModifiedAttributes(void) const;
        void SetModifiedAttributes(int flags, const MessageOrigin& origin = MessageOrigin());
index 3cf854f150056b44a9bb7e21e591b4815189ff87..4bafab4e138e2ce9f73633d592dee4ac8147dbfa 100644 (file)
@@ -203,16 +203,16 @@ TimePeriod::Ptr Dependency::GetPeriod(void) const
        return TimePeriod::GetByName(GetPeriodRaw());
 }
 
-void Dependency::ValidateFilters(const String& location, const Dictionary::Ptr& attrs)
+void Dependency::ValidateFilters(const String& location, const Dependency::Ptr& object)
 {
-       int sfilter = FilterArrayToInt(attrs->Get("states"), 0);
+       int sfilter = FilterArrayToInt(object->GetStates(), 0);
 
-       if (attrs->Get("parent_service_name") == Empty && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) {
+       if (object->GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) {
                ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
                    location + ": State filter is invalid for host dependency.");
        }
 
-       if (attrs->Get("parent_service_name") != Empty && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) {
+       if (!object->GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) {
                ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
                    location + ": State filter is invalid for service dependency.");
        }
index b35b2b07b72ca7963f76a33547d53f319bbbdf48..a3d9b8a71db523d1073143185563edb1e8b2014f 100644 (file)
@@ -49,7 +49,7 @@ public:
 
        static void RegisterApplyRuleHandler(void);
 
-       static void ValidateFilters(const String& location, const Dictionary::Ptr& attrs);
+       static void ValidateFilters(const String& location, const Dependency::Ptr& object);
 
 protected:
        virtual void OnConfigLoaded(void);
index 1c21c08b7a96783220081f31676bfa44954cba43..6d0f5d4872d2f2ca9c2217678a315d57dec02eb2 100644 (file)
@@ -493,21 +493,21 @@ int icinga::FilterArrayToInt(const Array::Ptr& typeFilters, int defaultValue)
        return resultTypeFilter;
 }
 
-void Notification::ValidateFilters(const String& location, const Dictionary::Ptr& attrs)
+void Notification::ValidateFilters(const String& location, const Notification::Ptr& object)
 {
-       int sfilter = FilterArrayToInt(attrs->Get("states"), 0);
+       int sfilter = FilterArrayToInt(object->GetStates(), 0);
 
-       if (attrs->Get("service_name") == Empty && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) {
+       if (object->GetServiceName().IsEmpty() && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) {
                ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
                    location + ": State filter is invalid.");
        }
 
-       if (attrs->Get("service_name") != Empty && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) {
+       if (!object->GetServiceName().IsEmpty() && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) {
                ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
                    location + ": State filter is invalid.");
        }
 
-       int tfilter = FilterArrayToInt(attrs->Get("types"), 0);
+       int tfilter = FilterArrayToInt(object->GetTypes(), 0);
 
        if ((tfilter & ~(1 << NotificationDowntimeStart | 1 << NotificationDowntimeEnd | 1 << NotificationDowntimeRemoved |
            1 << NotificationCustom | 1 << NotificationAcknowledgement | 1 << NotificationProblem | 1 << NotificationRecovery |
index 2bf6c095760771affb588bf88edd44b3e8cd7459..6e27e8fd4cd8561e661f1f73dcda1467148cfcc5 100644 (file)
@@ -106,7 +106,7 @@ public:
 
        static void RegisterApplyRuleHandler(void);
 
-       static void ValidateFilters(const String& location, const Dictionary::Ptr& attrs);
+       static void ValidateFilters(const String& location, const Notification::Ptr& object);
 
 protected:
        virtual void OnConfigLoaded(void);
index 7a7568aad18358249e78e347fc57a0bd8db8cdc3..5a595adecd5ece7494f1fa63d558d48b3a9e4a37 100644 (file)
@@ -183,11 +183,11 @@ void LivestatusListener::ClientHandler(const Socket::Ptr& client)
 }
 
 
-void LivestatusListener::ValidateSocketType(const String& location, const Dictionary::Ptr& attrs)
+void LivestatusListener::ValidateSocketType(const String& location, const LivestatusListener::Ptr& object)
 {
-       Value socket_type = attrs->Get("socket_type");
+       String socket_type = object->GetSocketType();
 
-       if (!socket_type.IsEmpty() && socket_type != "unix" && socket_type != "tcp") {
+       if (socket_type != "unix" && socket_type != "tcp") {
                ConfigCompilerContext::GetInstance()->AddMessage(true, "Validation failed for " +
                    location + ": Socket type '" + socket_type + "' is invalid.");
        }
index 14cf5527d53975717ad937999196d07ccf0b5f2f..ba298d4cdf11fb91c7fd0c4fbab22643395fda99 100644 (file)
@@ -44,7 +44,7 @@ public:
        static int GetClientsConnected(void);
        static int GetConnections(void);
 
-       static void ValidateSocketType(const String& location, const Dictionary::Ptr& attrs);
+       static void ValidateSocketType(const String& location, const LivestatusListener::Ptr& object);
 
 protected:
        virtual void Start(void);