Merge branch 'feature/apply-5789' into next

Fixes #5789
This commit is contained in:
Gunnar Beutner 2014-03-19 12:48:47 +01:00
commit c146ca272f
32 changed files with 692 additions and 226 deletions

View File

@ -113,7 +113,7 @@ If you require default macro definitions, you can add a macro dictionary as show
`CheckCommand` object.
object NotificationCommand "mail-service-notification" inherits "plugin-notification-command" {
command = [ (IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh") ],
command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ],
export_macros = [
"NOTIFICATIONTYPE",

View File

@ -273,7 +273,7 @@ Example:
...
{
check_interval = (MyCheckInterval / 2.5)
check_interval = MyCheckInterval / 2.5
}
More details in the chapter [Constant Expressions](#constant-expressions).

View File

@ -25,11 +25,11 @@ The user `icingaadmin` in the example below will get notified only on `WARNING`
object User "icingaadmin" {
display_name = "Icinga 2 Admin",
enable_notifications = 1,
notification_state_filter = (StateFilterOK |
StateFilterWarning |
StateFilterCritical),
notification_type_filter = (NotificationFilterProblem |
NotificationFilterRecovery),
notification_state_filter = StateFilterOK |
StateFilterWarning |
StateFilterCritical,
notification_type_filter = NotificationFilterProblem |
NotificationFilterRecovery,
macros = {
"email" = "icinga@localhost",
"pager" = "+49123456789"
@ -59,7 +59,7 @@ There are various macros available at runtime execution of the `NotificationComm
The example below may or may not fit your needs.
object NotificationCommand "mail-service-notification" inherits "plugin-notification-command" {
command = [ (IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh") ],
command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ],
export_macros = [
"NOTIFICATIONTYPE",
@ -91,18 +91,18 @@ to the defined notifications. That way you'll save duplicated attributes in each
notification_command = "mail-service-notification",
notification_state_filter = (StateFilterWarning |
StateFilterCritical |
StateFilterUnknown),
notification_type_filter = (NotificationFilterProblem |
NotificationFilterAcknowledgement |
NotificationFilterRecovery |
NotificationFilterCustom |
NotificationFilterFlappingStart |
NotificationFilterFlappingEnd |
NotificationFilterDowntimeStart |
NotificationFilterDowntimeEnd |
NotificationFilterDowntimeRemoved),
notification_state_filter = StateFilterWarning |
StateFilterCritical |
StateFilterUnknown,
notification_type_filter = NotificationFilterProblem |
NotificationFilterAcknowledgement |
NotificationFilterRecovery |
NotificationFilterCustom |
NotificationFilterFlappingStart |
NotificationFilterFlappingEnd |
NotificationFilterDowntimeStart |
NotificationFilterDowntimeEnd |
NotificationFilterDowntimeRemoved,
notification_period = "24x7"
}
@ -274,18 +274,18 @@ Available state and type filters for notifications are:
template Notification "generic-notification" {
notification_state_filter = (StateFilterWarning |
StateFilterCritical |
StateFilterUnknown),
notification_type_filter = (NotificationFilterProblem |
NotificationFilterAcknowledgement |
NotificationFilterRecovery |
NotificationFilterCustom |
NotificationFilterFlappingStart |
NotificationFilterFlappingEnd |
NotificationFilterDowntimeStart |
NotificationFilterDowntimeEnd |
NotificationFilterDowntimeRemoved),
notification_state_filter = StateFilterWarning |
StateFilterCritical |
StateFilterUnknown,
notification_type_filter = NotificationFilterProblem |
NotificationFilterAcknowledgement |
NotificationFilterRecovery |
NotificationFilterCustom |
NotificationFilterFlappingStart |
NotificationFilterFlappingEnd |
NotificationFilterDowntimeStart |
NotificationFilterDowntimeEnd |
NotificationFilterDowntimeRemoved,
}
> **Note**

View File

@ -317,14 +317,14 @@ Constants cannot be changed once they are set.
Simple calculations can be performed using the constant expression syntax:
{
check_interval = (15 * 60)
check_interval = 30 + 60
}
Valid operators include ~, +, -, * and /. The default precedence rules can be
Valid operators include ~, !, +, -, *, /, ==, !=, in and !in. The default precedence rules can be
overridden by grouping expressions using parentheses:
{
check_interval ((15 * 60) / 2)
check_interval = (30 + 60) / 2
}
Global constants may be used in constant expressions.
@ -334,13 +334,32 @@ Global constants may be used in constant expressions.
...
{
check_interval = (MyCheckInterval / 2.5)
check_interval = MyCheckInterval / 2.5
}
> **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

View File

@ -214,7 +214,7 @@ Example:
parent_host = "internet",
parent_service = "ping4",
state_filter = (StateFilterOK),
state_filter = StateFilterOK,
disable_checks = true
}
@ -230,7 +230,7 @@ Attributes:
disable_checks |**Optional.** Whether to disable checks when this dependency fails. Defaults to false.
disable_notifications|**Optional.** Whether to disable notifications when this dependency fails. Defaults to true.
period |**Optional.** Time period during which this dependency is enabled.
state_filter |**Optional.** A set of type filters when this dependency should be OK. Defaults to (StateFilterOK &#124; StateFilterWarning).
state_filter |**Optional.** A set of type filters when this dependency should be OK. Defaults to StateFilterOK &#124; StateFilterWarning.
Available state filters:
@ -252,12 +252,12 @@ Example:
enable_notifications = 1,
notification_period = "24x7",
notification_state_filter = (StateFilterOK |
StateFilterWarning |
StateFilterCritical |
StateFilterUnknown),
notification_type_filter = (NotificationFilterProblem |
NotificationFilterRecovery),
notification_state_filter = StateFilterOK |
StateFilterWarning |
StateFilterCritical |
StateFilterUnknown,
notification_type_filter = NotificationFilterProblem |
NotificationFilterRecovery,
macros = {
"name" = "Icinga 2 Admin",
"email" = "icinga@localhost",
@ -458,7 +458,7 @@ A notification command definition.
Example:
object NotificationCommand "mail-service-notification" inherits "plugin-notification-command" {
command = [ (IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh") ],
command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ],
export_macros = [
"NOTIFICATIONTYPE",
@ -588,7 +588,7 @@ Example:
logentries_age = 31d,
},
categories = (DbCatConfig | DbCatState)
categories = DbCatConfig | DbCatState
}
Attributes:
@ -672,7 +672,7 @@ Example:
logentries_age = 31d,
},
categories = (DbCatConfig | DbCatState)
categories = DbCatConfig | DbCatState
}
Attributes:
@ -877,7 +877,7 @@ a defined JSON file.
Example:
object IcingaStatusWriter "status" {
status_path = (IcingaLocalStateDir + "/cache/icinga2/status.json"),
status_path = IcingaLocalStateDir + "/cache/icinga2/status.json",
update_interval = 15s
}
@ -962,8 +962,8 @@ Example:
object Domain "dmz-1" {
acl = {
node1 = (DomainPrivCheckResult),
node2 = (DomainPrivReadWrite)
node1 = DomainPrivCheckResult,
node2 = DomainPrivReadWrite
}
}
@ -980,5 +980,5 @@ Domain ACLs:
DomainPrivRead | Endpoint reads local messages and relays them to remote nodes.
DomainPrivCheckResult | Endpoint accepts check result messages from remote nodes.
DomainPrivCommand | Endpoint accepts command messages from remote nodes.
DomainPrevReadOnly | Endpoint reads local messages and relays them to remote nodes.
DomainPrivReadWrite | Combination of (DomainPrivRead | DomainPrivCheckResult | DomainPrivCommand)
DomainPrevReadOnly | Equivalent to DomainPrivRead.
DomainPrivReadWrite | Equivalent to DomainPrivRead &#124; DomainPrivCheckResult &#124; DomainPrivCommand.

View File

@ -129,7 +129,7 @@ In order to load configuration files which were received from a remote Icinga 2
instance you will have to add the following include directive to your
`icinga2.conf` configuration file:
include (IcingaLocalStateDir + "/lib/icinga2/cluster/config/*/*")
include IcingaLocalStateDir + "/lib/icinga2/cluster/config/*/*"
### <a id="initial-cluster-sync"></a> Initial Cluster Sync

View File

@ -25,7 +25,7 @@ from the `icinga-node-dmz-1` endpoint.
object Domain "dmz-db" {
acl = {
icinga-node-dmz-1 = (DomainPrivReadOnly),
icinga-node-dmz-2 = (DomainPrivReadWrite)
icinga-node-dmz-1 = DomainPrivReadOnly,
icinga-node-dmz-2 = DomainPrivReadWrite
}
}

View File

@ -463,8 +463,8 @@ All state and type filter use long names or'd with a pipe together
notification_options w,u,c,r,f,s
notification_state_filter = (StateFilterWarning | StateFilterUnknown | StateFilterCritical),
notification_type_filter = (NotificationProblem | NotificationRecovery | NotificationFlappingStart | NotificationFlappingEnd | NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved)
notification_state_filter = StateFilterWarning | StateFilterUnknown | StateFilterCritical,
notification_type_filter = NotificationProblem | NotificationRecovery | NotificationFlappingStart | NotificationFlappingEnd | NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved
> **Note**
>

View File

@ -7,10 +7,10 @@ template User "generic-user" {
enable_notifications = true,
notification_period = "24x7",
notification_state_filter = (StateFilterWarning |
notification_state_filter = StateFilterWarning |
StateFilterCritical |
StateFilterUnknown),
notification_type_filter = (NotificationFilterProblem |
StateFilterUnknown,
notification_type_filter = NotificationFilterProblem |
NotificationFilterAcknowledgement |
NotificationFilterRecovery |
NotificationFilterCustom |
@ -18,5 +18,5 @@ template User "generic-user" {
NotificationFilterFlappingEnd |
NotificationFilterDowntimeStart |
NotificationFilterDowntimeEnd |
NotificationFilterDowntimeRemoved)
NotificationFilterDowntimeRemoved
}

View File

@ -5,11 +5,11 @@
template Notification "mail-notification" {
notification_command = "mail-service-notification",
notification_state_filter = (StateFilterOK |
notification_state_filter = StateFilterOK |
StateFilterWarning |
StateFilterCritical |
StateFilterUnknown),
notification_type_filter = (NotificationFilterProblem |
StateFilterUnknown,
notification_type_filter = NotificationFilterProblem |
NotificationFilterAcknowledgement |
NotificationFilterRecovery |
NotificationFilterCustom |
@ -17,13 +17,13 @@ template Notification "mail-notification" {
NotificationFilterFlappingEnd |
NotificationFilterDowntimeStart |
NotificationFilterDowntimeEnd |
NotificationFilterDowntimeRemoved),
NotificationFilterDowntimeRemoved,
notification_period = "24x7"
}
object NotificationCommand "mail-service-notification" inherits "plugin-notification-command" {
command = [ (IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh") ],
command = [ IcingaSysconfDir + "/icinga2/scripts/mail-notification.sh" ],
export_macros = [
"NOTIFICATIONTYPE",

View File

@ -6,6 +6,6 @@
object FileLogger "debug-file" {
severity = "debug",
path = (IcingaLocalStateDir + "/log/icinga2/debug.log")
path = IcingaLocalStateDir + "/log/icinga2/debug.log"
}

View File

@ -4,6 +4,6 @@
object FileLogger "main-log" {
severity = "information",
path = (IcingaLocalStateDir + "/log/icinga2/icinga2.log")
path = IcingaLocalStateDir + "/log/icinga2/icinga2.log"
}

View File

@ -136,6 +136,11 @@ std::string& String::GetData(void)
return m_Data;
}
const std::string& String::GetData(void) const
{
return m_Data;
}
size_t String::Find(const String& str, size_t pos) const
{
return m_Data.find(str, pos);

View File

@ -80,6 +80,7 @@ public:
size_t GetLength(void) const;
std::string& GetData(void);
const std::string& GetData(void) const;
size_t Find(const String& str, size_t pos = 0) const;
size_t RFind(const String& str, size_t pos = NPos) const;

View File

@ -196,7 +196,7 @@ ValueType Value::GetType(void) const
return static_cast<ValueType>(m_Value.which());
}
bool Value::operator==(bool rhs)
bool Value::operator==(bool rhs) const
{
if (!IsScalar())
return false;
@ -204,12 +204,12 @@ bool Value::operator==(bool rhs)
return static_cast<double>(*this) == rhs;
}
bool Value::operator!=(bool rhs)
bool Value::operator!=(bool rhs) const
{
return !(*this == rhs);
}
bool Value::operator==(int rhs)
bool Value::operator==(int rhs) const
{
if (!IsScalar())
return false;
@ -217,12 +217,12 @@ bool Value::operator==(int rhs)
return static_cast<double>(*this) == rhs;
}
bool Value::operator!=(int rhs)
bool Value::operator!=(int rhs) const
{
return !(*this == rhs);
}
bool Value::operator==(double rhs)
bool Value::operator==(double rhs) const
{
if (!IsScalar())
return false;
@ -230,32 +230,32 @@ bool Value::operator==(double rhs)
return static_cast<double>(*this) == rhs;
}
bool Value::operator!=(double rhs)
bool Value::operator!=(double rhs) const
{
return !(*this == rhs);
}
bool Value::operator==(const char *rhs)
bool Value::operator==(const char *rhs) const
{
return static_cast<String>(*this) == rhs;
}
bool Value::operator!=(const char *rhs)
bool Value::operator!=(const char *rhs) const
{
return !(*this == rhs);
}
bool Value::operator==(const String& rhs)
bool Value::operator==(const String& rhs) const
{
return static_cast<String>(*this) == rhs;
}
bool Value::operator!=(const String& rhs)
bool Value::operator!=(const String& rhs) const
{
return !(*this == rhs);
}
bool Value::operator==(const Value& rhs)
bool Value::operator==(const Value& rhs) const
{
if (IsEmpty() != rhs.IsEmpty())
return false;
@ -275,7 +275,7 @@ bool Value::operator==(const Value& rhs)
return static_cast<String>(*this) == static_cast<String>(rhs);
}
bool Value::operator!=(const Value& rhs)
bool Value::operator!=(const Value& rhs) const
{
return !(*this == rhs);
}

View File

@ -73,23 +73,23 @@ public:
operator double(void) const;
operator String(void) const;
bool operator==(bool rhs);
bool operator!=(bool rhs);
bool operator==(bool rhs) const;
bool operator!=(bool rhs) const;
bool operator==(int rhs);
bool operator!=(int rhs);
bool operator==(int rhs) const;
bool operator!=(int rhs) const;
bool operator==(double rhs);
bool operator!=(double rhs);
bool operator==(double rhs) const;
bool operator!=(double rhs) const;
bool operator==(const char *rhs);
bool operator!=(const char *rhs);
bool operator==(const char *rhs) const;
bool operator!=(const char *rhs) const;
bool operator==(const String& rhs);
bool operator!=(const String& rhs);
bool operator==(const String& rhs) const;
bool operator!=(const String& rhs) const;
bool operator==(const Value& rhs);
bool operator!=(const Value& rhs);
bool operator==(const Value& rhs) const;
bool operator!=(const Value& rhs) const;
template<typename T>
operator shared_ptr<T>(void) const

View File

@ -27,7 +27,7 @@ mkembedconfig_target(base-type.conf base-type.cpp)
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

View File

@ -18,28 +18,44 @@
******************************************************************************/
#include "config/aexpression.h"
#include "base/array.h"
#include "base/serializer.h"
#include "base/context.h"
#include "base/scriptfunction.h"
#include <boost/foreach.hpp>
using namespace icinga;
AExpression::AExpression(AOperator op, const AValue& operand1)
: m_Operator(op), m_Operand1(operand1)
AExpression::AExpression(AOperator op, const AValue& operand1, const DebugInfo& di)
: m_Operator(op), m_Operand1(operand1), m_DebugInfo(di)
{
ASSERT(op == AEReturn);
}
AExpression::AExpression(AOperator op, const AValue& operand1, const AValue& operand2)
: m_Operator(op), m_Operand1(operand1), m_Operand2(operand2)
AExpression::AExpression(AOperator op, const AValue& operand1, const AValue& operand2, const DebugInfo& di)
: m_Operator(op), m_Operand1(operand1), m_Operand2(operand2), m_DebugInfo(di)
{
ASSERT(op == AEAdd || op == AENegate || op == AESubtract || op == AEMultiply || op == AEDivide ||
op == AEBinaryAnd || op == AEBinaryOr || op == AEShiftLeft || op == AEShiftRight);
op == AEBinaryAnd || op == AEBinaryOr || op == AEShiftLeft || op == AEShiftRight ||
op == AEEqual || op == AENotEqual || op == AEIn || op == AENotIn ||
op == AELogicalAnd || op == AELogicalOr || op == AEFunctionCall);
}
Value AExpression::Evaluate(const Object::Ptr& thisRef) const
Value AExpression::Evaluate(const Dictionary::Ptr& locals) const
{
Value left, right;
Array::Ptr arr, arr2;
bool found;
String funcName;
ScriptFunction::Ptr func;
std::vector<Value> arguments;
left = m_Operand1.Evaluate(thisRef);
right = m_Operand2.Evaluate(thisRef);
left = m_Operand1.Evaluate(locals);
right = m_Operand2.Evaluate(locals);
std::ostringstream msgbuf;
msgbuf << "Evaluating AExpression " << m_DebugInfo << "; left=" << JsonSerialize(left) << "; right=" << JsonSerialize(right);
CONTEXT(msgbuf.str());
switch (m_Operator) {
case AEReturn:
@ -65,8 +81,65 @@ Value AExpression::Evaluate(const Object::Ptr& thisRef) const
return (long)left << (long)right;
case AEShiftRight:
return (long)left >> (long)right;
case AEEqual:
return left == right;
case AENotEqual:
return left != right;
case AEIn:
if (!right.IsObjectType<Array>())
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid right side argument for 'in' operator: " + JsonSerialize(right)));
arr = right;
found = false;
BOOST_FOREACH(const Value& value, arr) {
if (value == left) {
found = true;
break;
}
}
return found;
case AENotIn:
if (!right.IsObjectType<Array>())
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid right side argument for 'in' operator: " + JsonSerialize(right)));
arr = right;
found = false;
BOOST_FOREACH(const Value& value, arr) {
if (value == left) {
found = true;
break;
}
}
return !found;
case AELogicalAnd:
return (long)left && (long)right;
case AELogicalOr:
return (long)left || (long)right;
case AEFunctionCall:
funcName = left;
func = ScriptFunctionRegistry::GetInstance()->GetItem(funcName);
if (!func)
BOOST_THROW_EXCEPTION(std::invalid_argument("Function '" + funcName + "' does not exist."));
arr = right;
BOOST_FOREACH(const AExpression::Ptr& aexpr, arr) {
arguments.push_back(aexpr->Evaluate(locals));
}
return func->Invoke(arguments);
case AEArray:
arr = left;
arr2 = make_shared<Array>();
BOOST_FOREACH(const AExpression::Ptr& aexpr, arr) {
arr2->Add(aexpr->Evaluate(locals));
}
return arr2;
default:
ASSERT(!"Invalid operator.");
}
}

View File

@ -22,7 +22,8 @@
#include "config/i2-config.h"
#include "config/avalue.h"
#include "base/object.h"
#include "config/debuginfo.h"
#include "base/dictionary.h"
namespace icinga
{
@ -41,7 +42,15 @@ enum AOperator
AEBinaryAnd,
AEBinaryOr,
AEShiftLeft,
AEShiftRight
AEShiftRight,
AEEqual,
AENotEqual,
AEIn,
AENotIn,
AELogicalAnd,
AELogicalOr,
AEFunctionCall,
AEArray
};
/**
@ -52,15 +61,16 @@ class I2_CONFIG_API AExpression : public Object
public:
DECLARE_PTR_TYPEDEFS(AExpression);
AExpression(AOperator op, const AValue& operand1);
AExpression(AOperator op, const AValue& operand1, const AValue& operand2);
AExpression(AOperator op, const AValue& operand1, const DebugInfo& di);
AExpression(AOperator op, const AValue& operand1, const AValue& operand2, const DebugInfo& di);
Value Evaluate(const Object::Ptr& thisRef) const;
Value Evaluate(const Dictionary::Ptr& locals) const;
private:
AOperator m_Operator;
AValue m_Operand1;
AValue m_Operand2;
DebugInfo m_DebugInfo;
};
}

72
lib/config/applyrule.cpp Normal file
View File

@ -0,0 +1,72 @@
/******************************************************************************
* 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();
}

65
lib/config/applyrule.h Normal file
View File

@ -0,0 +1,65 @@
/******************************************************************************
* 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 */

View File

@ -35,17 +35,20 @@ AValue::AValue(AValueType type, const Value& value)
: m_Type(type), m_Value(value)
{ }
Value AValue::Evaluate(const Object::Ptr& thisRef) const
Value AValue::Evaluate(const Dictionary::Ptr& locals) const
{
switch (m_Type) {
case ATSimple:
return m_Value;
case ATVariable:
return ScriptVariable::Get(m_Value);
if (locals && locals->Contains(m_Value))
return locals->Get(m_Value);
else
return ScriptVariable::Get(m_Value);
case ATThisRef:
VERIFY(!"Not implemented.");
case ATExpression:
return m_Expression->Evaluate(thisRef);
return m_Expression->Evaluate(locals);
default:
ASSERT(!"Invalid type.");
}

View File

@ -22,7 +22,7 @@
#include "config/i2-config.h"
#include "base/value.h"
#include "base/object.h"
#include "base/dictionary.h"
namespace icinga
{
@ -50,7 +50,7 @@ public:
AValue(const shared_ptr<AExpression>& expr);
AValue(AValueType type, const Value& value);
Value Evaluate(const Object::Ptr& thisRef) const;
Value Evaluate(const Dictionary::Ptr& locals) const;
private:
AValueType m_Type;

View File

@ -222,8 +222,17 @@ false { yylval->num = 0; return T_NUMBER; }
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;
== return T_EQUAL;
!= return T_NOT_EQUAL;
!in return T_NOT_IN;
in return T_IN;
&& return T_LOGICAL_AND;
\|\| return T_LOGICAL_OR;
[a-zA-Z_][:a-zA-Z0-9\-_]* { yylval->text = strdup(yytext); return T_IDENTIFIER; }
\<[^\>]*\> { yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING_ANGLE; }
-?[0-9]+(\.[0-9]+)?ms { yylval->num = strtod(yytext, NULL) / 1000; return T_NUMBER; }
@ -232,7 +241,7 @@ const return T_CONST;
-?[0-9]+(\.[0-9]+)?m { yylval->num = strtod(yytext, NULL) * 60; return T_NUMBER; }
-?[0-9]+(\.[0-9]+)?s { yylval->num = strtod(yytext, NULL); return T_NUMBER; }
-?[0-9]+(\.[0-9]+)? { yylval->num = strtod(yytext, NULL); return T_NUMBER; }
= { yylval->op = OperatorSet; return T_EQUAL; }
= { yylval->op = OperatorSet; return T_SET; }
\+= { yylval->op = OperatorPlus; return T_PLUS_EQUAL; }
-= { yylval->op = OperatorMinus; return T_MINUS_EQUAL; }
\*= { yylval->op = OperatorMultiply; return T_MULTIPLY_EQUAL; }

View File

@ -27,11 +27,13 @@
#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>
@ -69,7 +71,7 @@ using namespace icinga;
%token <num> T_NUMBER
%token T_NULL
%token <text> T_IDENTIFIER
%token <op> T_EQUAL "= (T_EQUAL)"
%token <op> T_SET "= (T_SET)"
%token <op> T_PLUS_EQUAL "+= (T_PLUS_EQUAL)"
%token <op> T_MINUS_EQUAL "-= (T_MINUS_EQUAL)"
%token <op> T_MULTIPLY_EQUAL "*= (T_MULTIPLY_EQUAL)"
@ -78,6 +80,12 @@ using namespace icinga;
%token T_CONST "const (T_CONST)"
%token T_SHIFT_LEFT "<< (T_SHIFT_LEFT)"
%token T_SHIFT_RIGHT ">> (T_SHIFT_RIGHT)"
%token T_EQUAL "== (T_EQUAL)"
%token T_NOT_EQUAL "!= (T_NOT_EQUAL)"
%token T_IN "in (T_IN)"
%token T_NOT_IN "!in (T_NOT_IN)"
%token T_LOGICAL_AND "&& (T_LOGICAL_AND)"
%token T_LOGICAL_OR "|| (T_LOGICAL_OR)"
%token <type> T_TYPE_DICTIONARY "dictionary (T_TYPE_DICTIONARY)"
%token <type> T_TYPE_ARRAY "array (T_TYPE_ARRAY)"
%token <type> T_TYPE_NUMBER "number (T_TYPE_NUMBER)"
@ -96,11 +104,12 @@ using namespace icinga;
%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
%type <array> array_items_inner
%type <variant> simplevalue
%type <variant> value
%type <expr> expression
%type <exprl> expressions
@ -112,13 +121,20 @@ using namespace icinga;
%type <num> partial_specifier
%type <slist> object_inherits_list
%type <slist> object_inherits_specifier
%type <aexpr> aterm
%type <aexpr> aexpression
%type <num> variable_decl
%left T_LOGICAL_OR
%left T_LOGICAL_AND
%left T_IN
%left T_NOT_IN
%nonassoc T_EQUAL
%nonassoc T_NOT_EQUAL
%left '+' '-'
%left '*' '/'
%left '&'
%left '|'
%right '~'
%right '!'
%{
int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
@ -156,7 +172,7 @@ statements: /* empty */
| statements statement
;
statement: object | type | include | include_recursive | library | variable
statement: object | type | include | include_recursive | library | variable | apply
;
include: T_INCLUDE value
@ -191,7 +207,7 @@ library: T_LIBRARY T_STRING
}
;
variable: variable_decl identifier T_EQUAL value
variable: variable_decl identifier T_SET value
{
Value *value = $4;
if (value->IsObjectType<ExpressionList>()) {
@ -480,7 +496,7 @@ expression: identifier operator value
}
;
operator: T_EQUAL
operator: T_SET
| T_PLUS_EQUAL
| T_MINUS_EQUAL
| T_MULTIPLY_EQUAL
@ -490,12 +506,6 @@ operator: T_EQUAL
}
;
array: '[' array_items ']'
{
$$ = $2;
}
;
array_items: array_items_inner
{
$$ = $1;
@ -509,153 +519,176 @@ array_items_inner: /* empty */
{
$$ = NULL;
}
| value
| aexpression
{
$$ = new Array();
if ($1->IsObjectType<ExpressionList>()) {
ExpressionList::Ptr exprl = *$1;
Dictionary::Ptr dict = make_shared<Dictionary>();
exprl->Execute(dict);
delete $1;
$1 = new Value(dict);
}
$$->Add(*$1);
delete $1;
}
| array_items_inner ',' value
| array_items_inner ',' aexpression
{
if ($1)
$$ = $1;
else
$$ = new Array();
if ($3->IsObjectType<ExpressionList>()) {
ExpressionList::Ptr exprl = *$3;
Dictionary::Ptr dict = make_shared<Dictionary>();
exprl->Execute(dict);
delete $3;
$3 = new Value(dict);
}
$$->Add(*$3);
delete $3;
}
;
simplevalue: T_STRING
aexpression: T_STRING
{
$$ = new Value($1);
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, $1), yylloc));
free($1);
}
| T_NUMBER
{
$$ = new Value($1);
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, $1), yylloc));
}
| T_NULL
{
$$ = new Value();
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, Empty), yylloc));
}
| array
| T_IDENTIFIER '(' array_items ')'
{
if ($1 == NULL)
$1 = new Array();
Array::Ptr array = Array::Ptr($1);
$$ = new Value(array);
}
;
aterm: '(' aexpression ')'
{
$$ = $2;
}
aexpression: T_STRING
{
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, $1)));
Array::Ptr arguments = Array::Ptr($3);
$$ = new Value(make_shared<AExpression>(AEFunctionCall, AValue(ATSimple, $1), AValue(ATSimple, arguments), yylloc));
free($1);
}
| T_NUMBER
{
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, $1)));
}
| T_IDENTIFIER
{
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATVariable, $1)));
$$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATVariable, $1), yylloc));
free($1);
}
| '!' aexpression
{
$$ = new Value(make_shared<AExpression>(AENegate, static_cast<AExpression::Ptr>(*$2), yylloc));
delete $2;
}
| '~' aexpression
{
$$ = new Value(make_shared<AExpression>(AENegate, static_cast<AExpression::Ptr>(*$2)));
$$ = new Value(make_shared<AExpression>(AENegate, static_cast<AExpression::Ptr>(*$2), yylloc));
delete $2;
}
| aexpression '+' aexpression
| '[' array_items ']'
{
$$ = new Value(make_shared<AExpression>(AEAdd, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3)));
delete $1;
delete $3;
}
| aexpression '-' aexpression
{
$$ = new Value(make_shared<AExpression>(AESubtract, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3)));
delete $1;
delete $3;
}
| aexpression '*' aexpression
{
$$ = new Value(make_shared<AExpression>(AEMultiply, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3)));
delete $1;
delete $3;
}
| aexpression '/' aexpression
{
$$ = new Value(make_shared<AExpression>(AEDivide, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3)));
delete $1;
delete $3;
}
| aexpression '&' aexpression
{
$$ = new Value(make_shared<AExpression>(AEBinaryAnd, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3)));
delete $1;
delete $3;
}
| aexpression '|' aexpression
{
$$ = new Value(make_shared<AExpression>(AEBinaryOr, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3)));
delete $1;
delete $3;
}
| aexpression T_SHIFT_LEFT aexpression
{
$$ = new Value(make_shared<AExpression>(AEShiftLeft, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3)));
delete $1;
delete $3;
}
| aexpression T_SHIFT_RIGHT aexpression
{
$$ = new Value(make_shared<AExpression>(AEShiftRight, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3)));
delete $1;
delete $3;
$$ = new Value(make_shared<AExpression>(AEArray, AValue(ATSimple, Array::Ptr($2)), yylloc));
}
| '(' aexpression ')'
{
$$ = $2;
}
| aexpression '+' aexpression
{
$$ = new Value(make_shared<AExpression>(AEAdd, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
| aexpression '-' aexpression
{
$$ = new Value(make_shared<AExpression>(AESubtract, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
| aexpression '*' aexpression
{
$$ = new Value(make_shared<AExpression>(AEMultiply, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
| aexpression '/' aexpression
{
$$ = new Value(make_shared<AExpression>(AEDivide, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
| aexpression '&' aexpression
{
$$ = new Value(make_shared<AExpression>(AEBinaryAnd, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
| aexpression '|' aexpression
{
$$ = new Value(make_shared<AExpression>(AEBinaryOr, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
| aexpression T_IN aexpression
{
$$ = new Value(make_shared<AExpression>(AEIn, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
| aexpression T_NOT_IN aexpression
{
$$ = new Value(make_shared<AExpression>(AENotIn, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
| aexpression T_EQUAL aexpression
{
$$ = new Value(make_shared<AExpression>(AEEqual, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
| aexpression T_NOT_EQUAL aexpression
{
$$ = new Value(make_shared<AExpression>(AENotEqual, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
| aexpression T_SHIFT_LEFT aexpression
{
$$ = new Value(make_shared<AExpression>(AEShiftLeft, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
| aexpression T_SHIFT_RIGHT aexpression
{
$$ = new Value(make_shared<AExpression>(AEShiftRight, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
| aexpression T_LOGICAL_AND aexpression
{
$$ = new Value(make_shared<AExpression>(AELogicalAnd, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
| aexpression T_LOGICAL_OR aexpression
{
$$ = new Value(make_shared<AExpression>(AELogicalOr, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), yylloc));
delete $1;
delete $3;
}
;
value: simplevalue
| expressionlist
value: expressionlist
{
ExpressionList::Ptr exprl = ExpressionList::Ptr($1);
$$ = new Value(exprl);
}
| aterm
| aexpression
{
AExpression::Ptr aexpr = *$1;
$$ = new Value(aexpr->Evaluate(Object::Ptr()));
$$ = new Value(aexpr->Evaluate(Dictionary::Ptr()));
delete $1;
}
;
optional_template: /* empty */
| T_TEMPLATE
;
apply: T_APPLY optional_template identifier identifier T_TO identifier T_WHERE aexpression
{
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;
}
%%

View File

@ -19,6 +19,7 @@
#include "config/configitem.h"
#include "config/configcompilercontext.h"
#include "config/applyrule.h"
#include "base/application.h"
#include "base/dynamictype.h"
#include "base/objectlock.h"
@ -303,6 +304,9 @@ bool ConfigItem::ActivateItems(bool validateOnly)
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) {

View File

@ -43,7 +43,7 @@ add_library(icinga SHARED
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

90
lib/icinga/host-apply.cpp Normal file
View File

@ -0,0 +1,90 @@
/******************************************************************************
* 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());
Array::Ptr groups = host->GetGroups();
if (!groups)
groups = make_shared<Array>();
locals->Set("hostgroups", groups);
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;
}
std::ostringstream msgbuf2;
msgbuf2 << "Applying service template '" << rule.GetTemplate() << "' to host '" << host->GetName() << "' for rule " << rule.GetDebugInfo();
Log(LogDebug, "icinga", msgbuf2.str());
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();
}
}
}

View File

@ -24,6 +24,7 @@
#include "icinga/host.th"
#include "icinga/macroresolver.h"
#include "icinga/checkresult.h"
#include "config/applyrule.h"
#include "base/array.h"
#include "base/dictionary.h"
@ -101,6 +102,9 @@ public:
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);

View File

@ -18,7 +18,7 @@
add_library(methods SHARED
icingachecktask.cpp nullchecktask.cpp nulleventtask.cpp
pluginchecktask.cpp plugineventtask.cpp pluginnotificationtask.cpp
randomchecktask.cpp timeperiodtask.cpp
randomchecktask.cpp timeperiodtask.cpp utilityfuncs.cpp
)
target_link_libraries(methods ${Boost_LIBRARIES} base config icinga)

View File

@ -0,0 +1,35 @@
/******************************************************************************
* 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 "methods/utilityfuncs.h"
#include "base/scriptfunction.h"
#include "base/utility.h"
#include <boost/regex.hpp>
using namespace icinga;
REGISTER_SCRIPTFUNCTION(regex, &UtilityFuncs::Regex);
REGISTER_SCRIPTFUNCTION(match, &Utility::Match);
bool UtilityFuncs::Regex(const String& pattern, const String& text)
{
boost::regex expr(pattern.GetData());
boost::smatch what;
return boost::regex_search(text.GetData(), what, expr);
}

View File

@ -0,0 +1,43 @@
/******************************************************************************
* 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 UTILITYFUNCS_H
#define UTILITYFUNCS_H
#include "methods/i2-methods.h"
#include "base/qstring.h"
namespace icinga
{
/**
* @ingroup methods
*/
class I2_METHODS_API UtilityFuncs
{
public:
static bool Regex(const String& pattern, const String& text);
private:
UtilityFuncs(void);
};
}
#endif /* UTILITYFUNCS_H */