From 4ee05a1fa1914cd72fd18ae40ccac4f1fa9f1904 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 fec461845..e3402d8c2 100644 --- a/lib/config/applyrule.cpp +++ b/lib/config/applyrule.cpp @@ -12,9 +12,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) { } @@ -33,6 +33,11 @@ Expression::Ptr ApplyRule::GetFilter() const return m_Filter; } +String ApplyRule::GetZone() const +{ + return m_Zone; +} + String ApplyRule::GetPackage() const { return m_Package; @@ -59,7 +64,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); @@ -72,7 +77,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 0acc1c994..37d632c67 100644 --- a/lib/config/applyrule.hpp +++ b/lib/config/applyrule.hpp @@ -56,6 +56,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 @@ -78,7 +79,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); @@ -98,6 +99,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; @@ -118,7 +120,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 048cb29d7..8d1bdb814 100644 --- a/lib/config/config_parser.yy +++ b/lib/config/config_parser.yy @@ -1222,7 +1222,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 4c8fd6c5a..1ec358635 100644 --- a/lib/config/expression.cpp +++ b/lib/config/expression.cpp @@ -912,7 +912,7 @@ ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint*) con 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 e4120a006..08f67f050 100644 --- a/lib/config/expression.hpp +++ b/lib/config/expression.hpp @@ -824,11 +824,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()) { } @@ -841,6 +841,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 f1990c024..12712c3ab 100644 --- a/lib/config/vmops.hpp +++ b/lib/config/vmops.hpp @@ -116,11 +116,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 cd30d625212fccfb9a4f05183a6215705a86ae91 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 | 74 ++++++++++++++++++++++++++++++++++++ lib/icinga/apply-utility.hpp | 25 ++++++++++++ 3 files changed, 100 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 53aa214b2..1950bd12e 100644 --- a/lib/icinga/CMakeLists.txt +++ b/lib/icinga/CMakeLists.txt @@ -28,6 +28,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..4d8ba6939 --- /dev/null +++ b/lib/icinga/apply-utility.cpp @@ -0,0 +1,74 @@ +// SPDX-FileCopyrightText: 2019 Icinga GmbH +// SPDX-License-Identifier: GPL-3.0-or-later + +#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..22e43edda --- /dev/null +++ b/lib/icinga/apply-utility.hpp @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: 2019 Icinga GmbH +// SPDX-License-Identifier: GPL-3.0-or-later + +#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 3726b796812165f4e441fac9b1cee011fedd809e 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 87f4ad222..f7f97a524 100644 --- a/lib/icinga/dependency-apply.cpp +++ b/lib/icinga/dependency-apply.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2012 Icinga GmbH // SPDX-License-Identifier: GPL-2.0-or-later +#include "icinga/apply-utility.hpp" #include "icinga/dependency.hpp" #include "icinga/service.hpp" #include "config/configitembuilder.hpp" @@ -48,10 +49,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 1faf45a92..9b5c67e24 100644 --- a/lib/icinga/notification-apply.cpp +++ b/lib/icinga/notification-apply.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2012 Icinga GmbH // SPDX-License-Identifier: GPL-2.0-or-later +#include "icinga/apply-utility.hpp" #include "icinga/notification.hpp" #include "icinga/service.hpp" #include "config/configitembuilder.hpp" @@ -47,10 +48,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 de875695e..cc12b843b 100644 --- a/lib/icinga/scheduleddowntime-apply.cpp +++ b/lib/icinga/scheduleddowntime-apply.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2012 Icinga GmbH // SPDX-License-Identifier: GPL-2.0-or-later +#include "icinga/apply-utility.hpp" #include "icinga/scheduleddowntime.hpp" #include "icinga/service.hpp" #include "config/configitembuilder.hpp" @@ -46,10 +47,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 b32bd7b24..8162b9313 100644 --- a/lib/icinga/service-apply.cpp +++ b/lib/icinga/service-apply.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2012 Icinga GmbH // SPDX-License-Identifier: GPL-2.0-or-later +#include "icinga/apply-utility.hpp" #include "icinga/service.hpp" #include "config/configitembuilder.hpp" #include "config/applyrule.hpp" @@ -41,10 +42,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));