DSL: introduce on_config_committed

refs #3520
This commit is contained in:
Alexander A. Klimov 2019-08-29 17:32:22 +02:00
parent a65f2d6b41
commit 9c4f26bd60
8 changed files with 135 additions and 1 deletions

View File

@ -7,6 +7,7 @@
#include "base/logger.hpp" #include "base/logger.hpp"
#include "base/application.hpp" #include "base/application.hpp"
#include "base/scriptglobal.hpp" #include "base/scriptglobal.hpp"
#include "config/commitcontext.hpp"
#include "config/configcompiler.hpp" #include "config/configcompiler.hpp"
#include "config/configcompilercontext.hpp" #include "config/configcompilercontext.hpp"
#include "config/configitembuilder.hpp" #include "config/configitembuilder.hpp"
@ -240,6 +241,7 @@ bool DaemonUtility::LoadConfigFiles(const std::vector<std::string>& configs,
std::vector<ConfigItem::Ptr>& newItems, std::vector<ConfigItem::Ptr>& newItems,
const String& objectsFile, const String& varsfile) const String& objectsFile, const String& varsfile)
{ {
CommitContext cc;
ActivationScope ascope; ActivationScope ascope;
if (!DaemonUtility::ValidateConfigFiles(configs, objectsFile)) { if (!DaemonUtility::ValidateConfigFiles(configs, objectsFile)) {
@ -254,7 +256,7 @@ bool DaemonUtility::LoadConfigFiles(const std::vector<std::string>& configs,
WorkQueue upq(25000, Configuration::Concurrency); WorkQueue upq(25000, Configuration::Concurrency);
upq.SetName("DaemonUtility::LoadConfigFiles"); upq.SetName("DaemonUtility::LoadConfigFiles");
bool result = ConfigItem::CommitItems(ascope.GetContext(), upq, newItems); bool result = ConfigItem::CommitItems(ascope.GetContext(), upq, newItems) && cc.RunOnConfigCommitted();
if (!result) { if (!result) {
ConfigCompilerContext::GetInstance()->CancelObjectsFile(); ConfigCompilerContext::GetInstance()->CancelObjectsFile();

View File

@ -22,6 +22,7 @@ set(config_SOURCES
i2-config.hpp i2-config.hpp
activationcontext.cpp activationcontext.hpp activationcontext.cpp activationcontext.hpp
applyrule.cpp applyrule-targeted.cpp applyrule.hpp applyrule.cpp applyrule-targeted.cpp applyrule.hpp
commitcontext.cpp commitcontext.hpp
configcompiler.cpp configcompiler.hpp configcompiler.cpp configcompiler.hpp
configcompilercontext.cpp configcompilercontext.hpp configcompilercontext.cpp configcompilercontext.hpp
configfragment.hpp configfragment.hpp

View File

@ -0,0 +1,7 @@
/* Icinga 2 | (c) 2019 Icinga GmbH | GPLv2+ */
#include "config/commitcontext.hpp"
using namespace icinga;
thread_local CommitContext* CommitContext::m_Current = nullptr;

View File

@ -0,0 +1,86 @@
/* Icinga 2 | (c) 2019 Icinga GmbH | GPLv2+ */
#ifndef COMMITCONTEXT_H
#define COMMITCONTEXT_H
#include "base/debug.hpp"
#include "base/exception.hpp"
#include "base/logger.hpp"
#include "base/scriptframe.hpp"
#include "config/expression.hpp"
#include <exception>
#include <memory>
#include <utility>
#include <vector>
namespace icinga
{
class CommitContext
{
public:
static inline
CommitContext* GetCurrent()
{
return m_Current;
}
inline CommitContext() : m_Started(false)
{
VERIFY(!m_Current);
m_Current = this;
}
CommitContext(const CommitContext&) = delete;
CommitContext(CommitContext&&) = delete;
CommitContext& operator=(const CommitContext&) = delete;
CommitContext& operator=(CommitContext&&) = delete;
inline ~CommitContext()
{
VERIFY(m_Current);
m_Current = nullptr;
}
inline void RegisterOnConfigCommitted(std::shared_ptr<Expression> expr)
{
m_OnConfigCommitted.emplace_back(std::move(expr));
}
inline bool RunOnConfigCommitted()
{
m_Started = true;
for (auto& expr : m_OnConfigCommitted) {
if (!expr)
return false;
try {
ScriptFrame frame(false);
expr->Evaluate(frame);
} catch (const std::exception& ex) {
Log(LogCritical, "config", DiagnosticInformation(ex));
return false;
}
}
return true;
}
inline bool HasStarted()
{
return m_Started;
}
private:
static thread_local CommitContext* m_Current;
std::vector<std::shared_ptr<Expression>> m_OnConfigCommitted;
bool m_Started;
};
}
#endif /* COMMITCONTEXT_H */

View File

@ -156,6 +156,7 @@ template return T_TEMPLATE;
include return T_INCLUDE; include return T_INCLUDE;
include_recursive return T_INCLUDE_RECURSIVE; include_recursive return T_INCLUDE_RECURSIVE;
include_zones return T_INCLUDE_ZONES; include_zones return T_INCLUDE_ZONES;
on_config_committed return T_ON_CONFIG_COMMITTED;
library return T_LIBRARY; library return T_LIBRARY;
null return T_NULL; null return T_NULL;
true { yylval->boolean = 1; return T_BOOLEAN; } true { yylval->boolean = 1; return T_BOOLEAN; }

View File

@ -140,6 +140,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
%token T_INCLUDE "include (T_INCLUDE)" %token T_INCLUDE "include (T_INCLUDE)"
%token T_INCLUDE_RECURSIVE "include_recursive (T_INCLUDE_RECURSIVE)" %token T_INCLUDE_RECURSIVE "include_recursive (T_INCLUDE_RECURSIVE)"
%token T_INCLUDE_ZONES "include_zones (T_INCLUDE_ZONES)" %token T_INCLUDE_ZONES "include_zones (T_INCLUDE_ZONES)"
%token T_ON_CONFIG_COMMITTED "on_config_committed (T_ON_CONFIG_COMMITTED)"
%token T_LIBRARY "library (T_LIBRARY)" %token T_LIBRARY "library (T_LIBRARY)"
%token T_APPLY "apply (T_APPLY)" %token T_APPLY "apply (T_APPLY)"
%token T_TO "to (T_TO)" %token T_TO "to (T_TO)"
@ -195,6 +196,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
%right T_FOLLOWS %right T_FOLLOWS
%right T_INCLUDE T_INCLUDE_RECURSIVE T_INCLUDE_ZONES T_OBJECT T_TEMPLATE T_APPLY T_IMPORT T_ASSIGN T_IGNORE T_WHERE %right T_INCLUDE T_INCLUDE_RECURSIVE T_INCLUDE_ZONES T_OBJECT T_TEMPLATE T_APPLY T_IMPORT T_ASSIGN T_IGNORE T_WHERE
%right T_ON_CONFIG_COMMITTED
%right T_FUNCTION T_FOR %right T_FUNCTION T_FOR
%left T_SET T_SET_ADD T_SET_SUBTRACT T_SET_MULTIPLY T_SET_DIVIDE T_SET_MODULO T_SET_XOR T_SET_BINARY_AND T_SET_BINARY_OR %left T_SET T_SET_ADD T_SET_SUBTRACT T_SET_MULTIPLY T_SET_DIVIDE T_SET_MODULO T_SET_XOR T_SET_BINARY_AND T_SET_BINARY_OR
%right '?' ':' %right '?' ':'
@ -563,6 +565,10 @@ lterm: T_LIBRARY rterm
$$ = MakeLiteralRaw(); $$ = MakeLiteralRaw();
} }
| T_ON_CONFIG_COMMITTED rterm
{
$$ = new OnConfigCommittedExpression(std::shared_ptr<Expression>($2), @$);
}
| T_RETURN optional_rterm | T_RETURN optional_rterm
{ {
UseFlowControl(context, FlowControlReturn, @$); UseFlowControl(context, FlowControlReturn, @$);

View File

@ -1,6 +1,7 @@
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
#include "config/expression.hpp" #include "config/expression.hpp"
#include "config/commitcontext.hpp"
#include "config/configitem.hpp" #include "config/configitem.hpp"
#include "config/configcompiler.hpp" #include "config/configcompiler.hpp"
#include "config/vmops.hpp" #include "config/vmops.hpp"
@ -1046,6 +1047,22 @@ ExpressionResult IncludeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dh
return res; return res;
} }
ExpressionResult OnConfigCommittedExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
if (frame.Sandboxed)
BOOST_THROW_EXCEPTION(ScriptError("on_config_committed is not allowed in sandbox mode.", m_DebugInfo));
auto cc (CommitContext::GetCurrent());
if (!cc || cc->HasStarted()) {
BOOST_THROW_EXCEPTION(ScriptError("on_config_committed is not allowed after the config has been committed.", m_DebugInfo));
}
cc->RegisterOnConfigCommitted(m_Expr);
return Empty;
}
ExpressionResult BreakpointExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult BreakpointExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
ScriptBreakpoint(frame, nullptr, GetDebugInfo()); ScriptBreakpoint(frame, nullptr, GetDebugInfo());

View File

@ -955,6 +955,20 @@ private:
String m_Package; String m_Package;
}; };
class OnConfigCommittedExpression final : public DebuggableExpression
{
public:
OnConfigCommittedExpression(std::shared_ptr<Expression> expr, const DebugInfo& debugInfo = DebugInfo())
: DebuggableExpression(debugInfo), m_Expr(std::move(expr))
{ }
protected:
ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
private:
std::shared_ptr<Expression> m_Expr;
};
class BreakpointExpression final : public DebuggableExpression class BreakpointExpression final : public DebuggableExpression
{ {
public: public: