mirror of https://github.com/Icinga/icinga2.git
parent
b289987500
commit
7ee1278118
|
@ -121,6 +121,11 @@ Value AExpression::OpNegate(const AExpression *expr, const Dictionary::Ptr& loca
|
|||
return ~(long)expr->EvaluateOperand1(locals);
|
||||
}
|
||||
|
||||
Value AExpression::OpLogicalNegate(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return !expr->EvaluateOperand1(locals).ToBool();
|
||||
}
|
||||
|
||||
Value AExpression::OpAdd(const AExpression *expr, const Dictionary::Ptr& locals)
|
||||
{
|
||||
return expr->EvaluateOperand1(locals) + expr->EvaluateOperand2(locals);
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
static Value OpLiteral(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpVariable(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpNegate(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpLogicalNegate(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpAdd(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpSubtract(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
static Value OpMultiply(const AExpression *expr, const Dictionary::Ptr& locals);
|
||||
|
|
|
@ -18,19 +18,21 @@
|
|||
******************************************************************************/
|
||||
|
||||
#include "config/applyrule.h"
|
||||
#include "base/logger_fwd.h"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
ApplyRule::RuleMap ApplyRule::m_Rules;
|
||||
ApplyRule::CallbackMap ApplyRule::m_Callbacks;
|
||||
|
||||
ApplyRule::ApplyRule(const String& tmpl, const AExpression::Ptr& expression, const DebugInfo& di, const Dictionary::Ptr& scope)
|
||||
: m_Template(tmpl), m_Expression(expression), m_DebugInfo(di), m_Scope(scope)
|
||||
ApplyRule::ApplyRule(const String& name, const AExpression::Ptr& expression,
|
||||
const AExpression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope)
|
||||
: m_Name(name), m_Expression(expression), m_Filter(filter), m_DebugInfo(di), m_Scope(scope)
|
||||
{ }
|
||||
|
||||
String ApplyRule::GetTemplate(void) const
|
||||
String ApplyRule::GetName(void) const
|
||||
{
|
||||
return m_Template;
|
||||
return m_Name;
|
||||
}
|
||||
|
||||
AExpression::Ptr ApplyRule::GetExpression(void) const
|
||||
|
@ -38,6 +40,11 @@ AExpression::Ptr ApplyRule::GetExpression(void) const
|
|||
return m_Expression;
|
||||
}
|
||||
|
||||
AExpression::Ptr ApplyRule::GetFilter(void) const
|
||||
{
|
||||
return m_Filter;
|
||||
}
|
||||
|
||||
DebugInfo ApplyRule::GetDebugInfo(void) const
|
||||
{
|
||||
return m_DebugInfo;
|
||||
|
@ -48,30 +55,37 @@ Dictionary::Ptr ApplyRule::GetScope(void) const
|
|||
return m_Scope;
|
||||
}
|
||||
|
||||
void ApplyRule::AddRule(const String& sourceType, const String& tmpl, const String& targetType, const AExpression::Ptr& expression, const DebugInfo& di, const Dictionary::Ptr& scope)
|
||||
void ApplyRule::AddRule(const String& sourceType, const String& name,
|
||||
const AExpression::Ptr& expression, const AExpression::Ptr& filter,
|
||||
const DebugInfo& di, const Dictionary::Ptr& scope)
|
||||
{
|
||||
m_Rules[std::make_pair(sourceType, targetType)].push_back(ApplyRule(tmpl, expression, di, scope));
|
||||
m_Rules[sourceType].push_back(ApplyRule(name, expression, filter, di, scope));
|
||||
}
|
||||
|
||||
bool ApplyRule::EvaluateFilter(const Dictionary::Ptr& scope) const
|
||||
{
|
||||
return m_Filter->Evaluate(scope);
|
||||
}
|
||||
|
||||
void ApplyRule::EvaluateRules(void)
|
||||
{
|
||||
std::pair<TypeCombination, Callback> kv;
|
||||
std::pair<String, std::pair<Callback, int> > kv;
|
||||
BOOST_FOREACH(kv, m_Callbacks) {
|
||||
RuleMap::const_iterator it = m_Rules.find(kv.first);
|
||||
|
||||
if (it == m_Rules.end())
|
||||
continue;
|
||||
|
||||
kv.second(it->second);
|
||||
kv.second.first(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyRule::RegisterCombination(const String& sourceType, const String& targetType, const ApplyRule::Callback& callback)
|
||||
void ApplyRule::RegisterType(const String& sourceType, const ApplyRule::Callback& callback, int priority)
|
||||
{
|
||||
m_Callbacks[std::make_pair(sourceType, targetType)] = callback;
|
||||
m_Callbacks[sourceType] = make_pair(callback, priority);
|
||||
}
|
||||
|
||||
bool ApplyRule::IsValidCombination(const String& sourceType, const String& targetType)
|
||||
bool ApplyRule::IsValidType(const String& sourceType)
|
||||
{
|
||||
return m_Callbacks.find(std::make_pair(sourceType, targetType)) != m_Callbacks.end();
|
||||
return m_Callbacks.find(sourceType) != m_Callbacks.end();
|
||||
}
|
||||
|
|
|
@ -34,32 +34,37 @@ namespace icinga
|
|||
class I2_CONFIG_API ApplyRule
|
||||
{
|
||||
public:
|
||||
typedef std::pair<String, String> TypeCombination;
|
||||
typedef boost::function<void (const std::vector<ApplyRule>& rules)> Callback;
|
||||
typedef std::map<TypeCombination, Callback> CallbackMap;
|
||||
typedef std::map<TypeCombination, std::vector<ApplyRule> > RuleMap;
|
||||
typedef std::map<String, std::pair<Callback, int> > CallbackMap;
|
||||
typedef std::map<String, std::vector<ApplyRule> > RuleMap;
|
||||
|
||||
String GetTemplate(void) const;
|
||||
String GetName(void) const;
|
||||
AExpression::Ptr GetExpression(void) const;
|
||||
AExpression::Ptr GetFilter(void) const;
|
||||
DebugInfo GetDebugInfo(void) const;
|
||||
Dictionary::Ptr GetScope(void) const;
|
||||
|
||||
static void AddRule(const String& sourceType, const String& tmpl, const String& targetType, const AExpression::Ptr& expression, const DebugInfo& di, const Dictionary::Ptr& scope);
|
||||
bool EvaluateFilter(const Dictionary::Ptr& scope) const;
|
||||
|
||||
static void AddRule(const String& sourceType, const String& name, const AExpression::Ptr& expression,
|
||||
const AExpression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope);
|
||||
static void EvaluateRules(void);
|
||||
|
||||
static void RegisterCombination(const String& sourceType, const String& targetType, const ApplyRule::Callback& callback);
|
||||
static bool IsValidCombination(const String& sourceType, const String& targetType);
|
||||
static void RegisterType(const String& sourceType, const ApplyRule::Callback& callback, int priority);
|
||||
static bool IsValidType(const String& sourceType);
|
||||
|
||||
private:
|
||||
String m_Template;
|
||||
String m_Name;
|
||||
AExpression::Ptr m_Expression;
|
||||
AExpression::Ptr m_Filter;
|
||||
DebugInfo m_DebugInfo;
|
||||
Dictionary::Ptr m_Scope;
|
||||
|
||||
static CallbackMap m_Callbacks;
|
||||
static RuleMap m_Rules;
|
||||
|
||||
ApplyRule(const String& tmpl, const AExpression::Ptr& expression, const DebugInfo& di, const Dictionary::Ptr& scope);
|
||||
ApplyRule(const String& tmpl, const AExpression::Ptr& expression,
|
||||
const AExpression::Ptr& filter, const DebugInfo& di, const Dictionary::Ptr& scope);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -222,9 +222,10 @@ set return T_VAR;
|
|||
var return T_VAR;
|
||||
const return T_CONST;
|
||||
apply return T_APPLY;
|
||||
to return T_TO;
|
||||
where return T_WHERE;
|
||||
import return T_IMPORT;
|
||||
assign return T_ASSIGN;
|
||||
ignore return T_IGNORE;
|
||||
\<\< { yylval->op = &AExpression::OpShiftLeft; return T_SHIFT_LEFT; }
|
||||
\>\> { yylval->op = &AExpression::OpShiftRight; return T_SHIFT_RIGHT; }
|
||||
\<= { yylval->op = &AExpression::OpLessThanOrEqual; return T_LESS_THAN_OR_EQUAL; }
|
||||
|
|
|
@ -142,9 +142,10 @@ using namespace icinga;
|
|||
%token T_INHERITS "inherits (T_INHERITS)"
|
||||
%token T_PARTIAL "partial (T_PARTIAL)"
|
||||
%token T_APPLY "apply (T_APPLY)"
|
||||
%token T_TO "to (T_TO)"
|
||||
%token T_WHERE "where (T_WHERE)"
|
||||
%token T_IMPORT "import (T_IMPORT)"
|
||||
%token T_ASSIGN "assign (T_ASSIGN)"
|
||||
%token T_IGNORE "ignore (T_IGNORE)"
|
||||
%type <text> identifier
|
||||
%type <array> rterm_items
|
||||
%type <array> rterm_items_inner
|
||||
|
@ -192,6 +193,10 @@ static ConfigType::Ptr m_Type;
|
|||
|
||||
static Dictionary::Ptr m_ModuleScope;
|
||||
|
||||
static bool m_Apply;
|
||||
static AExpression::Ptr m_Assign;
|
||||
static AExpression::Ptr m_Ignore;
|
||||
|
||||
void ConfigCompiler::Compile(void)
|
||||
{
|
||||
m_ModuleScope = make_shared<Dictionary>();
|
||||
|
@ -542,6 +547,34 @@ lterm: identifier lbinary_op rterm
|
|||
$$ = new Value(make_shared<AExpression>(&AExpression::OpSetPlus, $1, expr, DebugInfoRange(@1, @5)));
|
||||
free($1);
|
||||
}
|
||||
| T_IMPORT rterm
|
||||
{
|
||||
AExpression::Ptr avar = make_shared<AExpression>(&AExpression::OpVariable, "__type", DebugInfoRange(@1, @2));
|
||||
AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$2);
|
||||
delete $2;
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpImport, avar, aexpr, DebugInfoRange(@1, @2)));
|
||||
}
|
||||
| T_ASSIGN T_WHERE rterm
|
||||
{
|
||||
if (!m_Apply)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("'assign' keyword not valid in this context."));
|
||||
|
||||
m_Assign = make_shared<AExpression>(&AExpression::OpLogicalOr, m_Assign, static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3));
|
||||
delete $3;
|
||||
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpLiteral, Empty, DebugInfoRange(@1, @3)));
|
||||
}
|
||||
| T_IGNORE T_WHERE rterm
|
||||
{
|
||||
if (!m_Apply)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("'ignore' keyword not valid in this context."));
|
||||
|
||||
m_Ignore = make_shared<AExpression>(&AExpression::OpLogicalOr, m_Ignore, static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3));
|
||||
|
||||
delete $3;
|
||||
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpLiteral, Empty, DebugInfoRange(@1, @3)));
|
||||
}
|
||||
| rterm
|
||||
{
|
||||
$$ = $1;
|
||||
|
@ -640,13 +673,6 @@ rterm: T_STRING
|
|||
$$ = new Value(make_shared<AExpression>(&AExpression::OpFunctionCall, $1, make_shared<AExpression>(&AExpression::OpLiteral, arguments, @3), DebugInfoRange(@1, @4)));
|
||||
free($1);
|
||||
}
|
||||
| T_IMPORT rterm
|
||||
{
|
||||
AExpression::Ptr avar = make_shared<AExpression>(&AExpression::OpVariable, "__type", DebugInfoRange(@1, @2));
|
||||
AExpression::Ptr aexpr = static_cast<AExpression::Ptr>(*$2);
|
||||
delete $2;
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpImport, avar, aexpr, DebugInfoRange(@1, @2)));
|
||||
}
|
||||
| T_IDENTIFIER
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpVariable, $1, @1));
|
||||
|
@ -654,7 +680,7 @@ rterm: T_STRING
|
|||
}
|
||||
| '!' rterm
|
||||
{
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpNegate, static_cast<AExpression::Ptr>(*$2), DebugInfoRange(@1, @2)));
|
||||
$$ = new Value(make_shared<AExpression>(&AExpression::OpLogicalNegate, static_cast<AExpression::Ptr>(*$2), DebugInfoRange(@1, @2)));
|
||||
delete $2;
|
||||
}
|
||||
| '~' rterm
|
||||
|
@ -688,22 +714,36 @@ rterm: T_STRING
|
|||
}
|
||||
;
|
||||
|
||||
optional_template: /* empty */
|
||||
| T_TEMPLATE
|
||||
;
|
||||
|
||||
apply: T_APPLY optional_template identifier identifier T_TO identifier T_WHERE rterm
|
||||
apply:
|
||||
{
|
||||
if (!ApplyRule::IsValidCombination($3, $6)) {
|
||||
BOOST_THROW_EXCEPTION(ConfigError("'apply' cannot be used with types '" + String($3) + "' and '" + String($6) + "'.") << errinfo_debuginfo(@1));
|
||||
}
|
||||
m_Apply = true;
|
||||
m_Assign = make_shared<AExpression>(&AExpression::OpLiteral, false, DebugInfo());
|
||||
m_Ignore = make_shared<AExpression>(&AExpression::OpLiteral, false, DebugInfo());
|
||||
}
|
||||
T_APPLY identifier rterm rterm
|
||||
{
|
||||
m_Apply = false;
|
||||
|
||||
Array::Ptr arguments = make_shared<Array>();
|
||||
arguments->Add(*$8);
|
||||
delete $8;
|
||||
AExpression::Ptr aname = static_cast<AExpression::Ptr>(*$4);
|
||||
delete $4;
|
||||
String type = $3;
|
||||
free($3);
|
||||
String name = aname->Evaluate(m_ModuleScope);
|
||||
|
||||
AExpression::Ptr aexpr = make_shared<AExpression>(&AExpression::OpFunctionCall, "bool", make_shared<AExpression>(&AExpression::OpLiteral, arguments, @8), @8);
|
||||
if (!ApplyRule::IsValidType(type))
|
||||
BOOST_THROW_EXCEPTION(ConfigError("'apply' cannot be used with type '" + type + "'") << errinfo_debuginfo(@2));
|
||||
|
||||
ApplyRule::AddRule($3, $4, $6, aexpr, DebugInfoRange(@1, @8), m_ModuleScope);
|
||||
AExpression::Ptr exprl = static_cast<AExpression::Ptr>(*$5);
|
||||
delete $5;
|
||||
|
||||
exprl->MakeInline();
|
||||
|
||||
// assign && !ignore
|
||||
AExpression::Ptr rex = make_shared<AExpression>(&AExpression::OpLogicalNegate, m_Ignore, DebugInfoRange(@2, @5));
|
||||
AExpression::Ptr filter = make_shared<AExpression>(&AExpression::OpLogicalAnd, m_Assign, rex, DebugInfoRange(@2, @5));
|
||||
ApplyRule::AddRule(type, name, exprl, filter, DebugInfoRange(@1, @5), m_ModuleScope);
|
||||
|
||||
m_Assign.reset();
|
||||
m_Ignore.reset();
|
||||
}
|
||||
%%
|
||||
|
|
|
@ -32,7 +32,7 @@ INITIALIZE_ONCE(&Host::RegisterApplyRuleHandler);
|
|||
|
||||
void Host::RegisterApplyRuleHandler(void)
|
||||
{
|
||||
ApplyRule::RegisterCombination("Service", "Host", &Host::EvaluateApplyRules);
|
||||
ApplyRule::RegisterType("Service", &Host::EvaluateApplyRules, 1);
|
||||
}
|
||||
|
||||
void Host::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
|
||||
|
@ -50,25 +50,15 @@ void Host::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
|
|||
msgbuf << "Evaluating 'apply' rule (" << di << ")";
|
||||
CONTEXT(msgbuf.str());
|
||||
|
||||
Value result = rule.GetExpression()->Evaluate(locals);
|
||||
|
||||
try {
|
||||
if (!static_cast<bool>(result))
|
||||
continue;
|
||||
} catch (...) {
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "Apply rule (" << di << ") returned invalid data type, expected bool: " + JsonSerialize(result);
|
||||
Log(LogCritical, "icinga", msgbuf.str());
|
||||
|
||||
if (!rule.EvaluateFilter(locals))
|
||||
continue;
|
||||
}
|
||||
|
||||
std::ostringstream msgbuf2;
|
||||
msgbuf2 << "Applying service template '" << rule.GetTemplate() << "' to host '" << host->GetName() << "' for rule " << di;
|
||||
msgbuf2 << "Applying service '" << rule.GetName() << "' to host '" << host->GetName() << "' for rule " << di;
|
||||
Log(LogDebug, "icinga", msgbuf2.str());
|
||||
|
||||
std::ostringstream namebuf;
|
||||
namebuf << host->GetName() << "!apply!" << rule.GetTemplate();
|
||||
namebuf << host->GetName() << "!" << rule.GetName();
|
||||
String name = namebuf.str();
|
||||
|
||||
ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(di);
|
||||
|
@ -76,11 +66,9 @@ void Host::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
|
|||
builder->SetName(name);
|
||||
builder->SetScope(rule.GetScope());
|
||||
|
||||
AExpression::Ptr atype = make_shared<AExpression>(&AExpression::OpLiteral, "Service", di);
|
||||
AExpression::Ptr atmpl = make_shared<AExpression>(&AExpression::OpLiteral, rule.GetTemplate(), di);
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpImport, atype, atmpl, di));
|
||||
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "host", make_shared<AExpression>(&AExpression::OpLiteral, host->GetName(), di), di));
|
||||
builder->AddExpression(make_shared<AExpression>(&AExpression::OpSet, "short_name", make_shared<AExpression>(&AExpression::OpLiteral, rule.GetName(), di), di));
|
||||
builder->AddExpression(rule.GetExpression());
|
||||
|
||||
ConfigItem::Ptr serviceItem = builder->Compile();
|
||||
serviceItem->Register();
|
||||
|
|
Loading…
Reference in New Issue