diff --git a/lib/icinga/CMakeLists.txt b/lib/icinga/CMakeLists.txt index 8187d48e8..888eced01 100644 --- a/lib/icinga/CMakeLists.txt +++ b/lib/icinga/CMakeLists.txt @@ -27,6 +27,7 @@ set(icinga_SOURCES i2-icinga.hpp icinga-itl.cpp apiactions.cpp apiactions.hpp apievents.cpp apievents.hpp + apply-utility.cpp apply-utility.hpp checkable.cpp checkable.hpp checkable-ti.hpp checkable-check.cpp checkable-comment.cpp checkable-dependency.cpp checkable-downtime.cpp checkable-event.cpp checkable-flapping.cpp diff --git a/lib/icinga/apply-utility.cpp b/lib/icinga/apply-utility.cpp new file mode 100644 index 000000000..1a6e24e9c --- /dev/null +++ b/lib/icinga/apply-utility.cpp @@ -0,0 +1,73 @@ +/* Icinga 2 | (c) 2019 Icinga GmbH | GPLv2+ */ + +#include "base/debuginfo.hpp" +#include "base/scriptframe.hpp" +#include "base/value.hpp" +#include "config/configcompiler.hpp" +#include "config/expression.hpp" +#include "icinga/apply-utility.hpp" +#include +#include + +using namespace icinga; + +/* Icinga DSL function which sets this.zone of a config object originated from an apply rule + * to either the zone of the config object the apply rule matched or the zone of the apply rule. + */ +static const Value l_MakeCommonZoneDsl = ([]() -> Value { + const char *dsl = R"EOF( + +function(parent_object_zone, apply_rule_zone) { + var child_zone = get_object(Zone, apply_rule_zone) + + var common_zone = if (child_zone && child_zone.global) { + parent_object_zone + } else { + apply_rule_zone + } + + if (common_zone != "") { + this.zone = common_zone + } +} + +)EOF"; + + ScriptFrame frame (false); + auto expr (ConfigCompiler::CompileText("", dsl)); + + return std::move(expr->Evaluate(frame).GetValue()); +})(); + +/** + * Create a DSL expression which sets this.zone of a config object originated from an apply rule + * + * @param parent_object_zone The zone of the config object the apply rule matched + * @param apply_rule_zone The zone of the apply rule + * + * @return The newly created DSL expression or nullptr if nothing to do + */ +std::unique_ptr ApplyUtility::MakeCommonZone(String parent_object_zone, String apply_rule_zone, const DebugInfo& debug_info) +{ + if (parent_object_zone == apply_rule_zone) { + if (parent_object_zone.IsEmpty()) { + return nullptr; + } + + /* this.zone = parent_object_zone */ + return std::unique_ptr(new SetExpression(MakeIndexer(ScopeThis, "zone"), OpSetLiteral, MakeLiteral(std::move(parent_object_zone)), debug_info)); + } + + std::vector> args; + args.reserve(3); + args.emplace_back(new GetScopeExpression(ScopeThis)); + args.emplace_back(MakeLiteral(std::move(parent_object_zone))); + args.emplace_back(MakeLiteral(std::move(apply_rule_zone))); + + /* l_MakeCommonZoneDsl.call(this, parent_object_zone, apply_rule_zone) */ + return std::unique_ptr(new FunctionCallExpression( + std::unique_ptr(new IndexerExpression(MakeLiteral(l_MakeCommonZoneDsl), MakeLiteral("call"))), + std::move(args), + debug_info + )); +} diff --git a/lib/icinga/apply-utility.hpp b/lib/icinga/apply-utility.hpp new file mode 100644 index 000000000..ef2c96e97 --- /dev/null +++ b/lib/icinga/apply-utility.hpp @@ -0,0 +1,24 @@ +/* Icinga 2 | (c) 2019 Icinga GmbH | GPLv2+ */ + +#ifndef APPLY_UTILITY_H +#define APPLY_UTILITY_H + +#include "base/debuginfo.hpp" +#include "base/string.hpp" +#include "config/expression.hpp" +#include +#include + +namespace icinga +{ + +namespace ApplyUtility +{ + +std::unique_ptr MakeCommonZone(String parent_object_zone, String apply_rule_zone, const DebugInfo& debug_info); + +} + +} + +#endif /* APPLY_UTILITY_H */