check_interval = (15 * 60)
}
-Valid operators include ~, +, -, * and /. The default precedence rules can be
+Valid operators include ~, +, -, *, /, == and !=. The default precedence rules can be
overridden by grouping expressions using parentheses:
{
> **Note**
>
-> Constant expressions are evaluated as soon as they're encountered in
-> the configuration file.
+> Constant expressions in attributes and variable definitions are evaluated as
+> soon as they're encountered in the configuration file.
+
+### <a id="apply"></a> Apply
+
+The `apply` keyword can be used to associate a template with another group of
+objects. The exact effect of this association depends on the two object types.
+
+ template Service "ping-service" {
+ short_name = "ping",
+ check_command = "ping4"
+ }
+
+ apply template Service "ping-service" to Host where (host == "localhost")
+
+In this example the `where` condition is a constant expression which is
+evaluated for all objects of type Host and a new service is created for each
+matching host.
+
+Depending on the object types used in the `apply` expression additional local
+variables may be available for use in the `where` condition.
### <a id="comments"></a> Comments
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
add_library(config SHARED
- aexpression.cpp avalue.cpp base-type.conf base-type.cpp
+ aexpression.cpp applyrule.cpp avalue.cpp base-type.conf base-type.cpp
configcompilercontext.cpp configcompiler.cpp configitembuilder.cpp
configitem.cpp ${FLEX_config_lexer_OUTPUTS} ${BISON_config_parser_OUTPUTS}
configtype.cpp expression.cpp expressionlist.cpp typerule.cpp typerulelist.cpp
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-present Icinga Development Team (http://www.icinga.org) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#include "config/applyrule.h"
+
+using namespace icinga;
+
+ApplyRule::RuleMap ApplyRule::m_Rules;
+ApplyRule::CallbackMap ApplyRule::m_Callbacks;
+
+ApplyRule::ApplyRule(const String& tmpl, const AExpression::Ptr& expression, const DebugInfo& di)
+ : m_Template(tmpl), m_Expression(expression), m_DebugInfo(di)
+{ }
+
+String ApplyRule::GetTemplate(void) const
+{
+ return m_Template;
+}
+
+AExpression::Ptr ApplyRule::GetExpression(void) const
+{
+ return m_Expression;
+}
+
+DebugInfo ApplyRule::GetDebugInfo(void) const
+{
+ return m_DebugInfo;
+}
+
+void ApplyRule::AddRule(const String& sourceType, const String& tmpl, const String& targetType, const AExpression::Ptr& expression, const DebugInfo& di)
+{
+ m_Rules[std::make_pair(sourceType, targetType)].push_back(ApplyRule(tmpl, expression, di));
+}
+
+void ApplyRule::EvaluateRules(void)
+{
+ std::pair<TypeCombination, Callback> kv;
+ BOOST_FOREACH(kv, m_Callbacks) {
+ RuleMap::const_iterator it = m_Rules.find(kv.first);
+
+ if (it == m_Rules.end())
+ continue;
+
+ kv.second(it->second);
+ }
+}
+
+void ApplyRule::RegisterCombination(const String& sourceType, const String& targetType, const ApplyRule::Callback& callback)
+{
+ m_Callbacks[std::make_pair(sourceType, targetType)] = callback;
+}
+
+bool ApplyRule::IsValidCombination(const String& sourceType, const String& targetType)
+{
+ return m_Callbacks.find(std::make_pair(sourceType, targetType)) != m_Callbacks.end();
+}
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-present Icinga Development Team (http://www.icinga.org) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#ifndef APPLYRULE_H
+#define APPLYRULE_H
+
+#include "config/i2-config.h"
+#include "config/aexpression.h"
+#include "config/debuginfo.h"
+#include "base/dynamictype.h"
+
+namespace icinga
+{
+
+/**
+ * @ingroup config
+ */
+class I2_CONFIG_API ApplyRule
+{
+public:
+ typedef std::pair<String, String> TypeCombination;
+ typedef boost::function<void (const std::vector<ApplyRule>& rules)> Callback;
+ typedef std::map<TypeCombination, Callback> CallbackMap;
+ typedef std::map<TypeCombination, std::vector<ApplyRule> > RuleMap;
+
+ String GetTemplate(void) const;
+ AExpression::Ptr GetExpression(void) const;
+ DebugInfo GetDebugInfo(void) const;
+
+ static void AddRule(const String& sourceType, const String& tmpl, const String& targetType, const AExpression::Ptr& expression, const DebugInfo& di);
+ static void EvaluateRules(void);
+
+ static void RegisterCombination(const String& sourceType, const String& targetType, const ApplyRule::Callback& callback);
+ static bool IsValidCombination(const String& sourceType, const String& targetType);
+
+private:
+ String m_Template;
+ AExpression::Ptr m_Expression;
+ DebugInfo m_DebugInfo;
+
+ static CallbackMap m_Callbacks;
+ static RuleMap m_Rules;
+
+ ApplyRule(const String& tmpl, const AExpression::Ptr& expression, const DebugInfo& di);
+};
+
+}
+
+#endif /* APPLYRULE_H */
set return T_VAR;
var return T_VAR;
const return T_CONST;
+apply return T_APPLY;
+to return T_TO;
+where return T_WHERE;
\<\< return T_SHIFT_LEFT;
\>\> return T_SHIFT_RIGHT;
[a-zA-Z_][:a-zA-Z0-9\-_]* { yylval->text = strdup(yytext); return T_IDENTIFIER; }
#include "config/typerule.h"
#include "config/typerulelist.h"
#include "config/aexpression.h"
+#include "config/applyrule.h"
#include "base/value.h"
#include "base/utility.h"
#include "base/array.h"
#include "base/scriptvariable.h"
#include "base/exception.h"
+#include "base/dynamictype.h"
#include <sstream>
#include <stack>
#include <boost/foreach.hpp>
%token T_LIBRARY "library (T_LIBRARY)"
%token T_INHERITS "inherits (T_INHERITS)"
%token T_PARTIAL "partial (T_PARTIAL)"
+%token T_APPLY "apply (T_APPLY)"
+%token T_TO "to (T_TO)"
+%token T_WHERE "where (T_WHERE)"
%type <text> identifier
%type <array> array
%type <array> array_items
| statements statement
;
-statement: object | type | include | include_recursive | library | variable
+statement: object | type | include | include_recursive | library | variable | apply
;
include: T_INCLUDE value
delete $1;
}
;
+
+optional_template: /* empty */
+ | T_TEMPLATE
+ ;
+
+apply: T_APPLY optional_template identifier identifier T_TO identifier T_WHERE aterm
+ {
+ if (!ApplyRule::IsValidCombination($3, $6)) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("'apply' cannot be used with types '" + String($3) + "' and '" + String($6) + "'."));
+ }
+
+ ApplyRule::AddRule($3, $4, $6, *$8, yylloc);
+ delete $8;
+ }
%%
#include "config/configitem.h"
#include "config/configcompilercontext.h"
+#include "config/applyrule.h"
#include "base/application.h"
#include "base/dynamictype.h"
#include "base/objectlock.h"
upq.Join();
+ Log(LogInformation, "config", "Evaluating 'apply' rules...");
+ ApplyRule::EvaluateRules();
+
Log(LogInformation, "config", "Validating config items (step 2)...");
BOOST_FOREACH(const ItemMap::value_type& kv, m_Items) {
api.cpp api.h checkcommand.cpp checkcommand.th checkresult.cpp checkresult.th
cib.cpp command.cpp command.th comment.cpp comment.th compatutility.cpp dependency.cpp dependency.th
domain.cpp domain.th downtime.cpp downtime.th eventcommand.cpp eventcommand.th
- externalcommandprocessor.cpp host.cpp host.th hostgroup.cpp hostgroup.th
+ externalcommandprocessor.cpp host.cpp host.th host-apply.cpp hostgroup.cpp hostgroup.th
icingaapplication.cpp icingaapplication.th icingastatuswriter.cpp
icingastatuswriter.th legacytimeperiod.cpp
macroprocessor.cpp macroresolver.cpp notificationcommand.cpp notificationcommand.th
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-present Icinga Development Team (http://www.icinga.org) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#include "icinga/host.h"
+#include "config/configitembuilder.h"
+#include "base/initialize.h"
+#include "base/dynamictype.h"
+#include "base/convert.h"
+#include "base/logger_fwd.h"
+#include "base/context.h"
+#include <boost/foreach.hpp>
+
+using namespace icinga;
+
+INITIALIZE_ONCE(&Host::RegisterApplyRuleHandler);
+
+void Host::RegisterApplyRuleHandler(void)
+{
+ ApplyRule::RegisterCombination("Service", "Host", &Host::EvaluateApplyRules);
+}
+
+void Host::EvaluateApplyRules(const std::vector<ApplyRule>& rules)
+{
+ BOOST_FOREACH(const Host::Ptr& host, DynamicType::GetObjects<Host>()) {
+ CONTEXT("Evaluating 'apply' rules for Host '" + host->GetName() + "'");
+
+ Dictionary::Ptr locals = make_shared<Dictionary>();
+ locals->Set("host", host->GetName());
+
+ BOOST_FOREACH(const ApplyRule& rule, rules) {
+ std::ostringstream msgbuf;
+ msgbuf << "Evaluating 'apply' rule (" << rule.GetDebugInfo() << ")";
+ CONTEXT(msgbuf.str());
+
+ Value result = rule.GetExpression()->Evaluate(locals);
+
+ try {
+ if (!static_cast<bool>(result))
+ continue;
+ } catch (...) {
+ std::ostringstream msgbuf;
+ msgbuf << "Apply rule (" << rule.GetDebugInfo() << ") returned invalid data type, expected bool: " + JsonSerialize(result);
+ Log(LogCritical, "icinga", msgbuf.str());
+
+ continue;
+ }
+
+ if (result.IsEmpty())
+ continue;
+
+ std::ostringstream namebuf;
+ namebuf << host->GetName() << "!apply!" << rule.GetTemplate();
+ String name = namebuf.str();
+
+ ConfigItemBuilder::Ptr builder = make_shared<ConfigItemBuilder>(rule.GetDebugInfo());
+ builder->SetType("Service");
+ builder->SetName(name);
+ builder->AddExpression("host", OperatorSet, host->GetName());
+
+ builder->AddParent(rule.GetTemplate());
+
+ ConfigItem::Ptr serviceItem = builder->Compile();
+ serviceItem->Register();
+ DynamicObject::Ptr dobj = serviceItem->Commit();
+ dobj->OnConfigLoaded();
+
+ Log(LogInformation, "icinga", "Rule result: " + Convert::ToString(result));
+ }
+ }
+}
#include "icinga/host.th"
#include "icinga/macroresolver.h"
#include "icinga/checkresult.h"
+#include "config/applyrule.h"
#include "base/array.h"
#include "base/dictionary.h"
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, String *result) const;
+ static void RegisterApplyRuleHandler(void);
+ static void EvaluateApplyRules(const std::vector<ApplyRule>& rules);
+
protected:
virtual void Stop(void);