From 7b4f1e217abc5d3d8a6b4c2e0da4d07186853af0 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 29 Jan 2015 10:09:53 +0100 Subject: [PATCH] Implement support for functions in set_if refs #7564 --- lib/icinga/icinga-type.conf | 2 ++ lib/icinga/macroprocessor.cpp | 43 ++++++++++++++++++++--------------- lib/icinga/macroprocessor.hpp | 5 ++++ lib/icinga/pluginutility.cpp | 6 ++--- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/lib/icinga/icinga-type.conf b/lib/icinga/icinga-type.conf index 5c2401c09ca..60470246fc4 100644 --- a/lib/icinga/icinga-type.conf +++ b/lib/icinga/icinga-type.conf @@ -201,11 +201,13 @@ %attribute %dictionary "*" { %attribute %string "key" %attribute %string "value" + %attribute %function "value" %attribute %string "description" %attribute %number "required" %attribute %number "skip_key" %attribute %number "repeat_key" %attribute %string "set_if" + %attribute %function "set_if" %attribute %number "order" } }, diff --git a/lib/icinga/macroprocessor.cpp b/lib/icinga/macroprocessor.cpp index 2d7d39362fa..4fc2434c44a 100644 --- a/lib/icinga/macroprocessor.cpp +++ b/lib/icinga/macroprocessor.cpp @@ -59,8 +59,10 @@ Value MacroProcessor::ResolveMacros(const Value& str, const ResolverList& resolv } result = resultArr; + } else if (str.IsObjectType()) { + result = EvaluateFunction(str, resolvers, cr, missingMacro, escapeFn, resolvedMacros, useResolvedMacros, 0); } else { - BOOST_THROW_EXCEPTION(std::invalid_argument("Command is not a string or array.")); + BOOST_THROW_EXCEPTION(std::invalid_argument("Macro is not a string or array.")); } return result; @@ -166,6 +168,26 @@ Value MacroProcessor::InternalResolveMacrosShim(const std::vector& args, resolvedMacros, useResolvedMacros, recursionLevel); } +Value MacroProcessor::EvaluateFunction(const Function::Ptr& func, const ResolverList& resolvers, + const CheckResult::Ptr& cr, String *missingMacro, + const MacroProcessor::EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros, + bool useResolvedMacros, int recursionLevel) +{ + Dictionary::Ptr resolvers_this = new Dictionary(); + + BOOST_FOREACH(const ResolverSpec& resolver, resolvers) { + resolvers_this->Set(resolver.first, resolver.second); + } + + resolvers_this->Set("macro", new Function(boost::bind(&MacroProcessor::InternalResolveMacrosShim, + _1, boost::cref(resolvers), cr, missingMacro, boost::cref(escapeFn), resolvedMacros, useResolvedMacros, + recursionLevel))); + + ScriptFrame frame(resolvers_this); + std::vector args; + return func->Invoke(args); +} + Value MacroProcessor::InternalResolveMacros(const String& str, const ResolverList& resolvers, const CheckResult::Ptr& cr, String *missingMacro, const MacroProcessor::EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros, @@ -210,23 +232,8 @@ Value MacroProcessor::InternalResolveMacros(const String& str, const ResolverLis } if (resolved_macro.IsObjectType()) { - Function::Ptr func = resolved_macro; - - if (!resolvers_this) { - resolvers_this = new Dictionary(); - - BOOST_FOREACH(const ResolverSpec& resolver, resolvers) { - resolvers_this->Set(resolver.first, resolver.second); - } - - resolvers_this->Set("macro", new Function(boost::bind(&MacroProcessor::InternalResolveMacrosShim, - _1, boost::cref(resolvers), cr, missingMacro, boost::cref(escapeFn), resolvedMacros, useResolvedMacros, - recursionLevel))); - } - - ScriptFrame frame(resolvers_this); - std::vector args; - resolved_macro = func->Invoke(args); + resolved_macro = EvaluateFunction(resolved_macro, resolvers, cr, missingMacro, escapeFn, + resolvedMacros, useResolvedMacros, recursionLevel); } if (!found) { diff --git a/lib/icinga/macroprocessor.hpp b/lib/icinga/macroprocessor.hpp index 78846aae767..ab667627018 100644 --- a/lib/icinga/macroprocessor.hpp +++ b/lib/icinga/macroprocessor.hpp @@ -61,6 +61,11 @@ class I2_ICINGA_API MacroProcessor const CheckResult::Ptr& cr, String *missingMacro, const MacroProcessor::EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros, int recursionLevel); + static Value EvaluateFunction(const Function::Ptr& func, const ResolverList& resolvers, + const CheckResult::Ptr& cr, String *missingMacro, + const MacroProcessor::EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros, + bool useResolvedMacros, int recursionLevel); + }; } diff --git a/lib/icinga/pluginutility.cpp b/lib/icinga/pluginutility.cpp index eeb892f402b..c01688b09da 100644 --- a/lib/icinga/pluginutility.cpp +++ b/lib/icinga/pluginutility.cpp @@ -109,7 +109,7 @@ void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkab arg.Key = kv.first; bool required = false; - String argval; + Value argval; if (arginfo.IsObjectType()) { Dictionary::Ptr argdict = arginfo; @@ -123,11 +123,11 @@ void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkab arg.RepeatKey = argdict->Get("repeat_key"); arg.Order = argdict->Get("order"); - String set_if = argdict->Get("set_if"); + Value set_if = argdict->Get("set_if"); if (!set_if.IsEmpty()) { String missingMacro; - String set_if_resolved = MacroProcessor::ResolveMacros(set_if, macroResolvers, + Value set_if_resolved = MacroProcessor::ResolveMacros(set_if, macroResolvers, cr, &missingMacro, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros);