[icinga-checkins] icinga.org: icinga2/master: Implement array validation

git at icinga.org git at icinga.org
Thu Mar 14 13:24:21 CET 2013


Module: icinga2
Branch: master
Commit: 5b0a413f3293ce74232d09cda2c3d2a3a7992faf
URL:    https://git.icinga.org/?p=icinga2.git;a=commit;h=5b0a413f3293ce74232d09cda2c3d2a3a7992faf

Author: Gunnar Beutner <gunnar.beutner at netways.de>
Date:   Thu Mar 14 13:24:07 2013 +0100

Implement array validation

Fixes #3701

---

 lib/config/base-type.conf   |    3 +-
 lib/config/configtype.cpp   |   86 +++++++++++++++++++++++++++++++
 lib/config/configtype.h     |    2 +
 lib/icinga/icinga-type.conf |  118 ++++++++++++++++++++++++++++++++++---------
 4 files changed, 182 insertions(+), 27 deletions(-)

diff --git a/lib/config/base-type.conf b/lib/config/base-type.conf
index b1615f2..60b719d 100644
--- a/lib/config/base-type.conf
+++ b/lib/config/base-type.conf
@@ -27,8 +27,7 @@ type DynamicObject {
 	%require "__type",
 	%attribute string "__type",
 
-	%attribute dictionary "methods" {
-	},
+	%attribute dictionary "methods",
 
 	%attribute any "custom::*"
 }
diff --git a/lib/config/configtype.cpp b/lib/config/configtype.cpp
index 9d8620f..6926419 100644
--- a/lib/config/configtype.cpp
+++ b/lib/config/configtype.cpp
@@ -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();
 	}
diff --git a/lib/config/configtype.h b/lib/config/configtype.h
index 4251a5f..f0e8b89 100644
--- a/lib/config/configtype.h
+++ b/lib/config/configtype.h
@@ -55,6 +55,8 @@ private:
 

 	static void ValidateDictionary(const Dictionary::Ptr& dictionary,

 	    const vector<TypeRuleList::Ptr>& ruleLists, vector<String>& locations);

+	static void ValidateArray(const Array::Ptr& array,

+	    const vector<TypeRuleList::Ptr>& ruleLists, vector<String>& locations);

 

 	static String LocationToString(const vector<String>& locations);

 };

diff --git a/lib/icinga/icinga-type.conf b/lib/icinga/icinga-type.conf
index b71009d..d2f4829 100644
--- a/lib/icinga/icinga-type.conf
+++ b/lib/icinga/icinga-type.conf
@@ -20,14 +20,28 @@
 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 {





More information about the icinga-checkins mailing list