From 74618c65986072590687fbd7a05c44179d8d4cd9 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 4 Jul 2019 18:25:23 +0200 Subject: [PATCH 1/3] Make apply rules zone-aware refs #6919 --- lib/config/applyrule.cpp | 13 +++++++++---- lib/config/applyrule.hpp | 6 ++++-- lib/config/config_parser.yy | 2 +- lib/config/expression.cpp | 2 +- lib/config/expression.hpp | 5 +++-- lib/config/vmops.hpp | 4 ++-- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/lib/config/applyrule.cpp b/lib/config/applyrule.cpp index 87399711e..5d401edc6 100644 --- a/lib/config/applyrule.cpp +++ b/lib/config/applyrule.cpp @@ -11,9 +11,9 @@ ApplyRule::RuleMap ApplyRule::m_Rules; ApplyRule::TypeMap ApplyRule::m_Types; ApplyRule::ApplyRule(String name, Expression::Ptr expression, - Expression::Ptr filter, String package, String fkvar, String fvvar, Expression::Ptr fterm, + Expression::Ptr filter, String zone, String package, String fkvar, String fvvar, Expression::Ptr fterm, bool ignoreOnError, DebugInfo di, Dictionary::Ptr scope) - : m_Name(std::move(name)), m_Expression(std::move(expression)), m_Filter(std::move(filter)), m_Package(std::move(package)), m_FKVar(std::move(fkvar)), + : m_Name(std::move(name)), m_Expression(std::move(expression)), m_Filter(std::move(filter)), m_Zone(std::move(zone)), m_Package(std::move(package)), m_FKVar(std::move(fkvar)), m_FVVar(std::move(fvvar)), m_FTerm(std::move(fterm)), m_IgnoreOnError(ignoreOnError), m_DebugInfo(std::move(di)), m_Scope(std::move(scope)), m_HasMatches(false) { } @@ -32,6 +32,11 @@ Expression::Ptr ApplyRule::GetFilter() const return m_Filter; } +String ApplyRule::GetZone() const +{ + return m_Zone; +} + String ApplyRule::GetPackage() const { return m_Package; @@ -58,7 +63,7 @@ Dictionary::Ptr ApplyRule::GetScope() const } void ApplyRule::AddRule(const String& sourceType, const String& targetType, const String& name, - const Expression::Ptr& expression, const Expression::Ptr& filter, const String& package, const String& fkvar, + const Expression::Ptr& expression, const Expression::Ptr& filter, const String& zone, const String& package, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm, bool ignoreOnError, const DebugInfo& di, const Dictionary::Ptr& scope) { auto actualTargetType (&targetType); @@ -71,7 +76,7 @@ void ApplyRule::AddRule(const String& sourceType, const String& targetType, cons } } - ApplyRule::Ptr rule = new ApplyRule(name, expression, filter, package, fkvar, fvvar, fterm, ignoreOnError, di, scope); + ApplyRule::Ptr rule = new ApplyRule(name, expression, filter, zone, package, fkvar, fvvar, fterm, ignoreOnError, di, scope); auto& rules (m_Rules[Type::GetByName(sourceType).get()]); if (!AddTargetedRule(rule, *actualTargetType, rules)) { diff --git a/lib/config/applyrule.hpp b/lib/config/applyrule.hpp index cf9b6e5e6..ec78af824 100644 --- a/lib/config/applyrule.hpp +++ b/lib/config/applyrule.hpp @@ -55,6 +55,7 @@ public: String GetName() const; Expression::Ptr GetExpression() const; Expression::Ptr GetFilter() const; + String GetZone() const; String GetPackage() const; inline const String& GetFKVar() const noexcept @@ -77,7 +78,7 @@ public: bool EvaluateFilter(ScriptFrame& frame) const; static void AddRule(const String& sourceType, const String& targetType, const String& name, const Expression::Ptr& expression, - const Expression::Ptr& filter, const String& package, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm, + const Expression::Ptr& filter, const String& zone, const String& package, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm, bool ignoreOnError, const DebugInfo& di, const Dictionary::Ptr& scope); static const std::vector& GetRules(const Type::Ptr& sourceType, const Type::Ptr& targetType); static const std::set& GetTargetedHostRules(const Type::Ptr& sourceType, const String& host); @@ -97,6 +98,7 @@ private: String m_Name; Expression::Ptr m_Expression; Expression::Ptr m_Filter; + String m_Zone; String m_Package; String m_FKVar; String m_FVVar; @@ -117,7 +119,7 @@ private: static const Value * GetConst(Expression* exp, const Dictionary::Ptr& constants); ApplyRule(String name, Expression::Ptr expression, - Expression::Ptr filter, String package, String fkvar, String fvvar, Expression::Ptr fterm, + Expression::Ptr filter, String zone, String package, String fkvar, String fvvar, Expression::Ptr fterm, bool ignoreOnError, DebugInfo di, Dictionary::Ptr scope); }; diff --git a/lib/config/config_parser.yy b/lib/config/config_parser.yy index 939681e68..7a8e8d4f9 100644 --- a/lib/config/config_parser.yy +++ b/lib/config/config_parser.yy @@ -1221,7 +1221,7 @@ apply: std::unique_ptr fterm{context->m_FTerm.top()}; context->m_FTerm.pop(); - $$ = new ApplyExpression(std::move(type), std::move(target), std::unique_ptr($4), std::move(filter), context->GetPackage(), std::move(fkvar), std::move(fvvar), std::move(fterm), std::move(*$7), $8, std::unique_ptr($10), DebugInfoRange(@2, @8)); + $$ = new ApplyExpression(std::move(type), std::move(target), std::unique_ptr($4), std::move(filter), context->GetZone(), context->GetPackage(), std::move(fkvar), std::move(fvvar), std::move(fterm), std::move(*$7), $8, std::unique_ptr($10), DebugInfoRange(@2, @8)); delete $7; } ; diff --git a/lib/config/expression.cpp b/lib/config/expression.cpp index 09b860cde..a20e3acdf 100644 --- a/lib/config/expression.cpp +++ b/lib/config/expression.cpp @@ -915,7 +915,7 @@ ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhin ExpressionResult nameres = m_Name->Evaluate(frame); CHECK_RESULT(nameres); - return VMOps::NewApply(frame, m_Type, m_Target, nameres.GetValue(), m_Filter, + return VMOps::NewApply(frame, m_Type, m_Target, nameres.GetValue(), m_Filter, m_Zone, m_Package, m_FKVar, m_FVVar, m_FTerm, m_ClosedVars, m_IgnoreOnError, m_Expression, m_DebugInfo); } diff --git a/lib/config/expression.hpp b/lib/config/expression.hpp index 644548d28..5cde480ed 100644 --- a/lib/config/expression.hpp +++ b/lib/config/expression.hpp @@ -830,11 +830,11 @@ class ApplyExpression final : public DebuggableExpression { public: ApplyExpression(String type, String target, std::unique_ptr name, - std::unique_ptr filter, String package, String fkvar, String fvvar, + std::unique_ptr filter, String zone, String package, String fkvar, String fvvar, std::unique_ptr fterm, std::map >&& closedVars, bool ignoreOnError, std::unique_ptr expression, const DebugInfo& debugInfo = DebugInfo()) : DebuggableExpression(debugInfo), m_Type(std::move(type)), m_Target(std::move(target)), - m_Name(std::move(name)), m_Filter(filter.release()), m_Package(std::move(package)), m_FKVar(std::move(fkvar)), m_FVVar(std::move(fvvar)), + m_Name(std::move(name)), m_Filter(filter.release()), m_Zone(std::move(zone)), m_Package(std::move(package)), m_FKVar(std::move(fkvar)), m_FVVar(std::move(fvvar)), m_FTerm(fterm.release()), m_IgnoreOnError(ignoreOnError), m_ClosedVars(std::move(closedVars)), m_Expression(expression.release()) { } @@ -847,6 +847,7 @@ private: String m_Target; std::unique_ptr m_Name; Expression::Ptr m_Filter; + String m_Zone; String m_Package; String m_FKVar; String m_FVVar; diff --git a/lib/config/vmops.hpp b/lib/config/vmops.hpp index ea3098359..53e19dae6 100644 --- a/lib/config/vmops.hpp +++ b/lib/config/vmops.hpp @@ -115,11 +115,11 @@ public: return new Function(name, wrapper, argNames); } - static inline Value NewApply(ScriptFrame& frame, const String& type, const String& target, const String& name, const Expression::Ptr& filter, + static inline Value NewApply(ScriptFrame& frame, const String& type, const String& target, const String& name, const Expression::Ptr& filter, const String& zone, const String& package, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm, const std::map >& closedVars, bool ignoreOnError, const Expression::Ptr& expression, const DebugInfo& debugInfo = DebugInfo()) { - ApplyRule::AddRule(type, target, name, expression, filter, package, fkvar, + ApplyRule::AddRule(type, target, name, expression, filter, zone, package, fkvar, fvvar, fterm, ignoreOnError, debugInfo, EvaluateClosedVars(frame, closedVars)); return Empty; From 3c09390c81d7c27c261ecf0827699c6be68aa864 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 10 Jul 2019 18:26:36 +0200 Subject: [PATCH 2/3] ApplyUtility::MakeCommonZone(): compute zone of a config object originated from an apply rule refs #6919 --- lib/icinga/CMakeLists.txt | 1 + lib/icinga/apply-utility.cpp | 73 ++++++++++++++++++++++++++++++++++++ lib/icinga/apply-utility.hpp | 24 ++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 lib/icinga/apply-utility.cpp create mode 100644 lib/icinga/apply-utility.hpp 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 */ From bb7f4c2b94cb8f91298ba752b4e1be36437c9208 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 16 Jul 2019 13:09:27 +0200 Subject: [PATCH 3/3] Set zones of config objects originated from an apply rules via ApplyUtility::MakeCommonZone() refs #6919 --- lib/icinga/dependency-apply.cpp | 10 +++++++--- lib/icinga/notification-apply.cpp | 10 +++++++--- lib/icinga/scheduleddowntime-apply.cpp | 10 +++++++--- lib/icinga/service-apply.cpp | 10 +++++++--- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/lib/icinga/dependency-apply.cpp b/lib/icinga/dependency-apply.cpp index 8681c4332..5db3c2ac8 100644 --- a/lib/icinga/dependency-apply.cpp +++ b/lib/icinga/dependency-apply.cpp @@ -1,5 +1,6 @@ /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ +#include "icinga/apply-utility.hpp" #include "icinga/dependency.hpp" #include "icinga/service.hpp" #include "config/configitembuilder.hpp" @@ -47,10 +48,13 @@ bool Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, cons if (service) builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "child_service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di)); - String zone = checkable->GetZoneName(); + { + auto expr (ApplyUtility::MakeCommonZone(checkable->GetZoneName(), rule.GetZone(), di)); - if (!zone.IsEmpty()) - builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "zone"), OpSetLiteral, MakeLiteral(zone), di)); + if (expr) { + builder.AddExpression(expr.release()); + } + } builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "package"), OpSetLiteral, MakeLiteral(rule.GetPackage()), di)); diff --git a/lib/icinga/notification-apply.cpp b/lib/icinga/notification-apply.cpp index f5b37643b..806858c25 100644 --- a/lib/icinga/notification-apply.cpp +++ b/lib/icinga/notification-apply.cpp @@ -1,5 +1,6 @@ /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ +#include "icinga/apply-utility.hpp" #include "icinga/notification.hpp" #include "icinga/service.hpp" #include "config/configitembuilder.hpp" @@ -46,10 +47,13 @@ bool Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, co if (service) builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di)); - String zone = checkable->GetZoneName(); + { + auto expr (ApplyUtility::MakeCommonZone(checkable->GetZoneName(), rule.GetZone(), di)); - if (!zone.IsEmpty()) - builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "zone"), OpSetLiteral, MakeLiteral(zone), di)); + if (expr) { + builder.AddExpression(expr.release()); + } + } builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "package"), OpSetLiteral, MakeLiteral(rule.GetPackage()), di)); diff --git a/lib/icinga/scheduleddowntime-apply.cpp b/lib/icinga/scheduleddowntime-apply.cpp index 4f8aa471f..9770a08fd 100644 --- a/lib/icinga/scheduleddowntime-apply.cpp +++ b/lib/icinga/scheduleddowntime-apply.cpp @@ -1,5 +1,6 @@ /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ +#include "icinga/apply-utility.hpp" #include "icinga/scheduleddowntime.hpp" #include "icinga/service.hpp" #include "config/configitembuilder.hpp" @@ -45,10 +46,13 @@ bool ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkabl if (service) builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di)); - String zone = checkable->GetZoneName(); + { + auto expr (ApplyUtility::MakeCommonZone(checkable->GetZoneName(), rule.GetZone(), di)); - if (!zone.IsEmpty()) - builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "zone"), OpSetLiteral, MakeLiteral(zone), di)); + if (expr) { + builder.AddExpression(expr.release()); + } + } builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "package"), OpSetLiteral, MakeLiteral(rule.GetPackage()), di)); diff --git a/lib/icinga/service-apply.cpp b/lib/icinga/service-apply.cpp index 4419e0b34..b556cb35e 100644 --- a/lib/icinga/service-apply.cpp +++ b/lib/icinga/service-apply.cpp @@ -1,5 +1,6 @@ /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ +#include "icinga/apply-utility.hpp" #include "icinga/service.hpp" #include "config/configitembuilder.hpp" #include "config/applyrule.hpp" @@ -40,10 +41,13 @@ bool Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& nam builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "name"), OpSetLiteral, MakeLiteral(name), di)); - String zone = host->GetZoneName(); + { + auto expr (ApplyUtility::MakeCommonZone(host->GetZoneName(), rule.GetZone(), di)); - if (!zone.IsEmpty()) - builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "zone"), OpSetLiteral, MakeLiteral(zone), di)); + if (expr) { + builder.AddExpression(expr.release()); + } + } builder.AddExpression(new SetExpression(MakeIndexer(ScopeThis, "package"), OpSetLiteral, MakeLiteral(rule.GetPackage()), di));