mirror of https://github.com/Icinga/icinga2.git
Refactor the config validator so that it doesn't require serialized objects
refs #7701
This commit is contained in:
parent
5321bc4643
commit
2d53e000c8
|
@ -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.");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
%require "__name",
|
||||
%attribute %string "__name",
|
||||
|
||||
%attribute %string "name",
|
||||
|
||||
%require "type",
|
||||
%attribute %string "type",
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
ValidateAttribute(field.Name, object->GetField(i), ruleLists, locations, utils);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
|
||||
DebugInfo GetDebugInfo(void) const;
|
||||
|
||||
void ValidateItem(const String& name, const Dictionary::Ptr& attrs,
|
||||
void ValidateItem(const String& name, const Object::Ptr& object,
|
||||
const DebugInfo& debugInfo, const TypeRuleUtilities *utils);
|
||||
|
||||
void Register(void);
|
||||
|
@ -65,7 +65,10 @@ private:
|
|||
TypeRuleList::Ptr m_RuleList;
|
||||
DebugInfo m_DebugInfo; /**< Debug information. */
|
||||
|
||||
static void ValidateDictionary(const Dictionary::Ptr& dictionary,
|
||||
static void ValidateAttribute(const String& key, const Value& value,
|
||||
const std::vector<TypeRuleList::Ptr>& ruleLists, std::vector<String>& locations,
|
||||
const TypeRuleUtilities *utils);
|
||||
static void ValidateObject(const Object::Ptr& object,
|
||||
const std::vector<TypeRuleList::Ptr>& ruleLists, std::vector<String>& locations,
|
||||
const TypeRuleUtilities *utils);
|
||||
static void ValidateArray(const Array::Ptr& array,
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue