Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DSL: introduce on_config_committed #7460

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/cli/daemonutility.cpp
Expand Up @@ -7,6 +7,7 @@
#include "base/logger.hpp"
#include "base/application.hpp"
#include "base/scriptglobal.hpp"
#include "config/commitcontext.hpp"
#include "config/configcompiler.hpp"
#include "config/configcompilercontext.hpp"
#include "config/configitembuilder.hpp"
Expand Down Expand Up @@ -240,6 +241,7 @@ bool DaemonUtility::LoadConfigFiles(const std::vector<std::string>& configs,
std::vector<ConfigItem::Ptr>& newItems,
const String& objectsFile, const String& varsfile)
{
CommitContext cc;
ActivationScope ascope;

if (!DaemonUtility::ValidateConfigFiles(configs, objectsFile)) {
Expand All @@ -254,7 +256,7 @@ bool DaemonUtility::LoadConfigFiles(const std::vector<std::string>& configs,

WorkQueue upq(25000, Configuration::Concurrency);
upq.SetName("DaemonUtility::LoadConfigFiles");
bool result = ConfigItem::CommitItems(ascope.GetContext(), upq, newItems);
bool result = ConfigItem::CommitItems(ascope.GetContext(), upq, newItems) && cc.RunOnConfigCommitted();

if (result) {
try {
Expand Down
1 change: 1 addition & 0 deletions lib/config/CMakeLists.txt
Expand Up @@ -22,6 +22,7 @@ set(config_SOURCES
i2-config.hpp
activationcontext.cpp activationcontext.hpp
applyrule.cpp applyrule-targeted.cpp applyrule.hpp
commitcontext.cpp commitcontext.hpp
configcompiler.cpp configcompiler.hpp
configcompilercontext.cpp configcompilercontext.hpp
configfragment.hpp
Expand Down
7 changes: 7 additions & 0 deletions lib/config/commitcontext.cpp
@@ -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;
86 changes: 86 additions & 0 deletions lib/config/commitcontext.hpp
@@ -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 */
1 change: 1 addition & 0 deletions lib/config/config_lexer.ll
Expand Up @@ -156,6 +156,7 @@ template return T_TEMPLATE;
include return T_INCLUDE;
include_recursive return T_INCLUDE_RECURSIVE;
include_zones return T_INCLUDE_ZONES;
on_config_committed return T_ON_CONFIG_COMMITTED;
library return T_LIBRARY;
null return T_NULL;
true { yylval->boolean = 1; return T_BOOLEAN; }
Expand Down
6 changes: 6 additions & 0 deletions lib/config/config_parser.yy
Expand Up @@ -140,6 +140,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
%token T_INCLUDE "include (T_INCLUDE)"
%token T_INCLUDE_RECURSIVE "include_recursive (T_INCLUDE_RECURSIVE)"
%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_APPLY "apply (T_APPLY)"
%token T_TO "to (T_TO)"
Expand Down Expand Up @@ -195,6 +196,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig

%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_ON_CONFIG_COMMITTED
%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
%right '?' ':'
Expand Down Expand Up @@ -563,6 +565,10 @@ lterm: T_LIBRARY rterm

$$ = MakeLiteralRaw();
}
| T_ON_CONFIG_COMMITTED rterm
{
$$ = new OnConfigCommittedExpression(std::shared_ptr<Expression>($2), @$);
}
| T_RETURN optional_rterm
{
UseFlowControl(context, FlowControlReturn, @$);
Expand Down
17 changes: 17 additions & 0 deletions lib/config/expression.cpp
@@ -1,6 +1,7 @@
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */

#include "config/expression.hpp"
#include "config/commitcontext.hpp"
#include "config/configitem.hpp"
#include "config/configcompiler.hpp"
#include "config/vmops.hpp"
Expand Down Expand Up @@ -1046,6 +1047,22 @@ ExpressionResult IncludeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dh
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
{
ScriptBreakpoint(frame, nullptr, GetDebugInfo());
Expand Down
14 changes: 14 additions & 0 deletions lib/config/expression.hpp
Expand Up @@ -950,6 +950,20 @@ class IncludeExpression final : public DebuggableExpression
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
{
public:
Expand Down