]> granicus.if.org Git - icinga2/commitdiff
Implement array validation
authorGunnar Beutner <gunnar.beutner@netways.de>
Thu, 14 Mar 2013 12:24:07 +0000 (13:24 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Thu, 14 Mar 2013 12:24:07 +0000 (13:24 +0100)
Fixes #3701

lib/config/base-type.conf
lib/config/configtype.cpp
lib/config/configtype.h
lib/icinga/icinga-type.conf

index b1615f2ddaa036c272c1fed6c07b0a8dee5eb8fb..60b719d2f393791bd96674677cae26e1c3a473a3 100644 (file)
@@ -27,8 +27,7 @@ type DynamicObject {
        %require "__type",
        %attribute string "__type",
 
-       %attribute dictionary "methods" {
-       },
+       %attribute dictionary "methods",
 
        %attribute any "custom::*"
 }
index 9d8620fcd68f20e32a9d3a8748031508f0301441..6926419d2660e57f248ffe21afe245e4b2d0abce 100644 (file)
@@ -173,6 +173,92 @@ void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary,
 
                if (!subRuleLists.empty() && value.IsObjectType<Dictionary>())
                        ValidateDictionary(value, subRuleLists, locations);
+               else if (!subRuleLists.empty() && value.IsObjectType<Array>())
+                       ValidateArray(value, subRuleLists, locations);
+
+               locations.pop_back();
+       }
+}
+
+/**
+ * @threadsafety Always.
+ */
+void ConfigType::ValidateArray(const Array::Ptr& array,
+    const vector<TypeRuleList::Ptr>& ruleLists, vector<String>& locations)
+{
+       BOOST_FOREACH(const TypeRuleList::Ptr& ruleList, ruleLists) {
+               BOOST_FOREACH(const String& require, ruleList->GetRequires()) {
+                       long index = Convert::ToLong(require);
+
+                       locations.push_back("Attribute '" + require + "'");
+
+                       if (array->GetLength() < index) {
+                               ConfigCompilerContext::GetContext()->AddError(false,
+                                   "Required array index is missing: " + LocationToString(locations));
+                       }
+
+                       locations.pop_back();
+               }
+
+               String validator = ruleList->GetValidator();
+
+               if (!validator.IsEmpty()) {
+                       ScriptFunction::Ptr func = ScriptFunction::GetByName(validator);
+
+                       if (!func)
+                               BOOST_THROW_EXCEPTION(invalid_argument("Validator function '" + validator + "' does not exist."));
+
+                       vector<Value> arguments;
+                       arguments.push_back(LocationToString(locations));
+                       arguments.push_back(array);
+
+                       ScriptTask::Ptr task = boost::make_shared<ScriptTask>(func, arguments);
+                       task->Start();
+                       task->GetResult();
+               }
+       }
+
+       ObjectLock olock(array);
+
+       int index = 0;
+       String key;
+       BOOST_FOREACH(const Value& value, array) {
+               key = Convert::ToString(index);
+               index++;
+
+               TypeValidationResult overallResult = ValidationUnknownField;
+               vector<TypeRuleList::Ptr> subRuleLists;
+
+               locations.push_back("Attribute '" + key + "'");
+
+               BOOST_FOREACH(const TypeRuleList::Ptr& ruleList, ruleLists) {
+                       TypeRuleList::Ptr subRuleList;
+                       TypeValidationResult result = ruleList->ValidateAttribute(key, value, &subRuleList);
+
+                       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::GetContext()->AddError(true, "Unknown attribute: " + LocationToString(locations));
+               else if (overallResult == ValidationInvalidType)
+                       ConfigCompilerContext::GetContext()->AddError(false, "Invalid type for array index: " + LocationToString(locations));
+
+               if (!subRuleLists.empty() && value.IsObjectType<Dictionary>())
+                       ValidateDictionary(value, subRuleLists, locations);
+               else if (!subRuleLists.empty() && value.IsObjectType<Array>())
+                       ValidateArray(value, subRuleLists, locations);
 
                locations.pop_back();
        }
index 4251a5f3d73104646858cf576e7c0198b1105ebf..f0e8b89b814d2dfd94d1899a1f497d27763b4521 100644 (file)
@@ -55,6 +55,8 @@ private:
 \r
        static void ValidateDictionary(const Dictionary::Ptr& dictionary,\r
            const vector<TypeRuleList::Ptr>& ruleLists, vector<String>& locations);\r
+       static void ValidateArray(const Array::Ptr& array,\r
+           const vector<TypeRuleList::Ptr>& ruleLists, vector<String>& locations);\r
 \r
        static String LocationToString(const vector<String>& locations);\r
 };\r
index b71009d67b99442cc0b6d75fc9fdb0efeca89e63..d2f48291abd3d14daf9f29724047591187b7359b 100644 (file)
 type Host {
        %attribute string "display_name",
        %attribute string "hostcheck",
-       %attribute array "hostgroups",
-       %attribute array "hostdependencies",
-       %attribute array "servicedependencies",
+       %attribute array "hostgroups" {
+               %attribute string "*"
+       },
+       %attribute array "hostdependencies" {
+               %attribute string "*"
+       },
+       %attribute array "servicedependencies" {
+               %attribute dictionary "*" {
+                       %require "host",
+                       %attribute string "host",
+
+                       %require "service",
+                       %attribute string "service"
+               }
+       },
        %attribute dictionary "services" {
                %validator "ValidateServiceDictionary",
 
                %attribute dictionary "*" {
-                       %attribute array "templates",
+                       %attribute array "templates" {
+                               %attribute string "*"
+                       },
 
                        %attribute string "short_name",
 
@@ -39,23 +53,43 @@ type Host {
                        %attribute number "check_interval",
                        %attribute number "retry_interval",
 
-                       %attribute array "servicegroups",
-                       %attribute array "checkers",
-                       %attribute array "hostdependencies",
-                       %attribute array "servicedependencies"
+                       %attribute array "servicegroups" {
+                               %attribute string "*"
+                       },
+                       %attribute array "checkers" {
+                               %attribute string "*"
+                       },
+                       %attribute array "hostdependencies" {
+                               %attribute string "*"
+                       },
+                       %attribute array "servicedependencies" {
+                               %attribute dictionary "*" {
+                                       %require "host",
+                                       %attribute string "host",
+
+                                       %require "service",
+                                       %attribute string "service"
+                               }
+                       }
                }
        },
 
        %attribute dictionary "notifications" {
                %attribute dictionary "*" {
-                       %attribute array "templates",
+                       %attribute array "templates" {
+                               %attribute string "*"
+                       },
 
                        %attribute dictionary "macros" {
                                %attribute string "*"
                        },
 
-                       %attribute array "users",
-                       %attribute array "groups"
+                       %attribute array "users" {
+                               %attribute string "*"
+                       },
+                       %attribute array "groups" {
+                               %attribute string "*"
+                       }
                }
        },
 
@@ -68,8 +102,12 @@ type Host {
        %attribute dictionary "macros" {
                %attribute string "*"
        },
-       %attribute array "servicegroups",
-       %attribute array "checkers"
+       %attribute array "servicegroups" {
+               %attribute string "*"
+       },
+       %attribute array "checkers" {
+               %attribute string "*"
+       }
 }
 
 type HostGroup {
@@ -98,16 +136,32 @@ type Service {
        %attribute dictionary "macros" {
                %attribute string "*"
        },
-       %attribute array "check_command",
+       %attribute array "check_command" {
+               %attribute string "*"
+       },
        %attribute string "check_command",
        %attribute number "max_check_attempts",
        %attribute string "check_period",
        %attribute number "check_interval",
        %attribute number "retry_interval",
-       %attribute array "hostdependencies",
-       %attribute array "servicedependencies",
-       %attribute array "servicegroups",
-       %attribute array "checkers",
+       %attribute array "hostdependencies" {
+               %attribute string "*"
+       },
+       %attribute array "servicedependencies" {
+               %attribute dictionary "*" {
+                       %require "host",
+                       %attribute string "host",
+
+                       %require "service",
+                       %attribute string "service"
+               }
+       },
+       %attribute array "servicegroups" {
+               %attribute string "*"
+       },
+       %attribute array "checkers" {
+               %attribute string "*"
+       },
 
        %require "methods",
        %attribute dictionary "methods" {
@@ -117,14 +171,20 @@ type Service {
 
        %attribute dictionary "notifications" {
                %attribute dictionary "*" {
-                       %attribute array "templates",
+                       %attribute array "templates" {
+                               %attribute string "*"
+                       },
 
                        %attribute dictionary "macros" {
                                %attribute string "*"
                        },
 
-                       %attribute array "users",
-                       %attribute array "groups"
+                       %attribute array "users" {
+                               %attribute string "*"
+                       },
+                       %attribute array "groups" {
+                               %attribute string "*"
+                       }
                }
        },
 
@@ -152,10 +212,16 @@ type Notification {
                %attribute string "*"
        },
 
-       %attribute array "users",
-       %attribute array "groups",
+       %attribute array "users" {
+               %attribute string "*"
+       },
+       %attribute array "groups" {
+               %attribute string "*"
+       },
 
-       %attribute array "notification_command",
+       %attribute array "notification_command" {
+               %attribute string "*"
+       },
        %attribute string "notification_command"
 }
 
@@ -166,7 +232,9 @@ type User {
                %attribute string "*"
        },
 
-       %attribute array "groups"
+       %attribute array "groups" {
+               %attribute string "*"
+       }
 }
 
 type UserGroup {