Implement support for constants in the config parser.

Refs #4946
This commit is contained in:
Gunnar Beutner 2013-12-04 11:04:36 +01:00
parent 25cece444d
commit e540685e13
9 changed files with 102 additions and 55 deletions

View File

@ -273,12 +273,21 @@ Parent objects are resolved in the order they're specified using the
### Variables ### Variables
Global variables can be set using the `set` keyword: Global variables can be set using the `var` and `const` keywords:
set VarName = "some value" var VarName = "some value"
The value can be a string, number, array or a dictionary. The value can be a string, number, array or a dictionary.
Variables can be set multiple times unless they were introduced using
the `const` keyword.
> **Note**
>
> The `set` keyword is an alias for the `var` keyword and is available
> in order to provide compatibility with older versions. Its use is
> deprecated.
### Constant Expressions ### Constant Expressions
Simple calculations can be performed using the constant expression syntax: Simple calculations can be performed using the constant expression syntax:
@ -287,7 +296,7 @@ Simple calculations can be performed using the constant expression syntax:
check_interval = (15 * 60) 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: overridden by grouping expressions using parentheses:
{ {
@ -296,7 +305,7 @@ overridden by grouping expressions using parentheses:
Global variables may be used in constant expressions. Global variables may be used in constant expressions.
set MyCheckInterval = 10m var MyCheckInterval = 10m
... ...

View File

@ -1,7 +1,7 @@
/** /**
* Global macros * Global macros
*/ */
set IcingaMacros = { var IcingaMacros = {
plugindir = "/usr/lib/nagios/plugins" plugindir = "/usr/lib/nagios/plugins"
} }

View File

@ -335,6 +335,8 @@ int main(int argc, char **argv)
Application::DeclareStatePath(Application::GetLocalStateDir() + "/lib/icinga2/icinga2.state"); Application::DeclareStatePath(Application::GetLocalStateDir() + "/lib/icinga2/icinga2.state");
Application::DeclarePidPath(Application::GetLocalStateDir() + "/run/icinga2/icinga2.pid"); Application::DeclarePidPath(Application::GetLocalStateDir() + "/run/icinga2/icinga2.pid");
Application::MakeVariablesConstant();
Log(LogInformation, "icinga-app", "Icinga application loader (version: " + Application::GetVersion() + ")"); Log(LogInformation, "icinga-app", "Icinga application loader (version: " + Application::GetVersion() + ")");
String appType = LoadAppType(Application::GetApplicationType()); String appType = LoadAppType(Application::GetApplicationType());

View File

@ -17,68 +17,68 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/ ******************************************************************************/
set StateOK = (0) const StateOK = 0
set StateWarning = (1) const StateWarning = 1
set StateCritical = (2) const StateCritical = 2
set StateUnknown = (3) const StateUnknown = 3
/* /*
* Converting states to their filter values: 1<<state * Converting states to their filter values: 1<<state
*/ */
set StateFilterOK = (1<<StateOK) const StateFilterOK = (1<<StateOK)
set StateFilterWarning = (1<<StateWarning) const StateFilterWarning = (1<<StateWarning)
set StateFilterCritical = (1<<StateCritical) const StateFilterCritical = (1<<StateCritical)
set StateFilterUnknown = (1<<StateUnknown) const StateFilterUnknown = (1<<StateUnknown)
set NotificationDowntimeStart = (0) const NotificationDowntimeStart = 0
set NotificationDowntimeEnd = (1) const NotificationDowntimeEnd = 1
set NotificationDowntimeRemoved = (2) const NotificationDowntimeRemoved = 2
set NotificationCustom = (3) const NotificationCustom = 3
set NotificationAcknowledgement = (4) const NotificationAcknowledgement = 4
set NotificationProblem = (5) const NotificationProblem = 5
set NotificationRecovery = (6) const NotificationRecovery = 6
set NotificationFlappingStart = (7) const NotificationFlappingStart = 7
set NotificationFlappingEnd = (8) const NotificationFlappingEnd = 8
/* /*
* Converting notification types to their filter values: 1<<type * Converting notification types to their filter values: 1<<type
*/ */
set NotificationFilterDowntimeStart = (1<<NotificationDowntimeStart) const NotificationFilterDowntimeStart = (1<<NotificationDowntimeStart)
set NotificationFilterDowntimeEnd = (1<<NotificationDowntimeEnd) const NotificationFilterDowntimeEnd = (1<<NotificationDowntimeEnd)
set NotificationFilterDowntimeRemoved = (1<<NotificationDowntimeRemoved) const NotificationFilterDowntimeRemoved = (1<<NotificationDowntimeRemoved)
set NotificationFilterCustom = (1<<NotificationCustom) const NotificationFilterCustom = (1<<NotificationCustom)
set NotificationFilterAcknowledgement = (1<<NotificationAcknowledgement) const NotificationFilterAcknowledgement = (1<<NotificationAcknowledgement)
set NotificationFilterProblem = (1<<NotificationProblem) const NotificationFilterProblem = (1<<NotificationProblem)
set NotificationFilterRecovery = (1<<NotificationRecovery) const NotificationFilterRecovery = (1<<NotificationRecovery)
set NotificationFilterFlappingStart = (1<<NotificationFlappingStart) const NotificationFilterFlappingStart = (1<<NotificationFlappingStart)
set NotificationFilterFlappingEnd = (1<<NotificationFlappingEnd) const NotificationFilterFlappingEnd = (1<<NotificationFlappingEnd)
/* /*
* Domain privilege flags * Domain privilege flags
*/ */
set DomainPrivRead = (1<<0) const DomainPrivRead = (1<<0)
set DomainPrivCheckResult = (1<<1) const DomainPrivCheckResult = (1<<1)
set DomainPrivCommand = (1<<2) const DomainPrivCommand = (1<<2)
set DomainPrivReadOnly = (DomainPrivRead) const DomainPrivReadOnly = (DomainPrivRead)
set DomainPrivReadWrite = (DomainPrivRead | DomainPrivCheckResult | DomainPrivCommand) const DomainPrivReadWrite = (DomainPrivRead | DomainPrivCheckResult | DomainPrivCommand)
/* /*
* IDO filter categories * IDO filter categories
*/ */
set DbCatConfig = (1 << 0) const DbCatConfig = (1 << 0)
set DbCatState = (1 << 1) const DbCatState = (1 << 1)
set DbCatAcknowledgement = (1 << 2) const DbCatAcknowledgement = (1 << 2)
set DbCatComment = (1 << 3) const DbCatComment = (1 << 3)
set DbCatDowntime = (1 << 4) const DbCatDowntime = (1 << 4)
set DbCatEventHandler = (1 << 5) const DbCatEventHandler = (1 << 5)
set DbCatExternalCommand = (1 << 6) const DbCatExternalCommand = (1 << 6)
set DbCatFlapping = (1 << 7) const DbCatFlapping = (1 << 7)
set DbCatCheck = (1 << 8) const DbCatCheck = (1 << 8)
set DbCatLog = (1 << 9) const DbCatLog = (1 << 9)
set DbCatNotification = (1 << 10) const DbCatNotification = (1 << 10)
set DbCatProgramStatus = (1 << 11) const DbCatProgramStatus = (1 << 11)
set DbCatRetention = (1 << 12) const DbCatRetention = (1 << 12)
set DbCatStateHistory = (1 << 13) const DbCatStateHistory = (1 << 13)
set DbCatEverything = (~0) const DbCatEverything = (~0)

View File

@ -730,6 +730,17 @@ void Application::DeclareApplicationType(const String& type)
ScriptVariable::Set("ApplicationType", type, false); ScriptVariable::Set("ApplicationType", type, false);
} }
void Application::MakeVariablesConstant(void)
{
ScriptVariable::GetByName("IcingaPrefixDir")->SetConstant(true);
ScriptVariable::GetByName("IcingaSysconfDir")->SetConstant(true);
ScriptVariable::GetByName("IcingaLocalStateDir")->SetConstant(true);
ScriptVariable::GetByName("IcingaPkgDataDir")->SetConstant(true);
ScriptVariable::GetByName("IcingaStatePath")->SetConstant(true);
ScriptVariable::GetByName("IcingaPidPath")->SetConstant(true);
ScriptVariable::GetByName("ApplicationType")->SetConstant(true);
}
/** /**
* Returns the global thread pool. * Returns the global thread pool.
* *

View File

@ -91,6 +91,8 @@ public:
static String GetApplicationType(void); static String GetApplicationType(void);
static void DeclareApplicationType(const String& type); static void DeclareApplicationType(const String& type);
static void MakeVariablesConstant(void);
static ThreadPool& GetTP(void); static ThreadPool& GetTP(void);
static String GetVersion(void); static String GetVersion(void);

View File

@ -71,6 +71,9 @@ ScriptVariable::Ptr ScriptVariable::Set(const String& name, const Value& value,
sv = make_shared<ScriptVariable>(value); sv = make_shared<ScriptVariable>(value);
ScriptVariableRegistry::GetInstance()->Register(name, sv); ScriptVariableRegistry::GetInstance()->Register(name, sv);
} else if (overwrite) { } else if (overwrite) {
if (sv->IsConstant())
BOOST_THROW_EXCEPTION(std::invalid_argument("Tried to modify read-only script variable '" + name + "'"));
sv->SetData(value); sv->SetData(value);
} }

View File

@ -219,7 +219,9 @@ null return T_NULL;
partial return T_PARTIAL; partial return T_PARTIAL;
true { yylval->num = 1; return T_NUMBER; } true { yylval->num = 1; return T_NUMBER; }
false { yylval->num = 0; return T_NUMBER; } false { yylval->num = 0; return T_NUMBER; }
set return T_SET; set return T_VAR;
var return T_VAR;
const return T_CONST;
\<\< return T_SHIFT_LEFT; \<\< return T_SHIFT_LEFT;
\>\> return T_SHIFT_RIGHT; \>\> return T_SHIFT_RIGHT;
[a-zA-Z_][:a-zA-Z0-9\-_]* { yylval->text = strdup(yytext); return T_IDENTIFIER; } [a-zA-Z_][:a-zA-Z0-9\-_]* { yylval->text = strdup(yytext); return T_IDENTIFIER; }

View File

@ -74,7 +74,8 @@ using namespace icinga;
%token <op> T_MINUS_EQUAL "-= (T_MINUS_EQUAL)" %token <op> T_MINUS_EQUAL "-= (T_MINUS_EQUAL)"
%token <op> T_MULTIPLY_EQUAL "*= (T_MULTIPLY_EQUAL)" %token <op> T_MULTIPLY_EQUAL "*= (T_MULTIPLY_EQUAL)"
%token <op> T_DIVIDE_EQUAL "/= (T_DIVIDE_EQUAL)" %token <op> T_DIVIDE_EQUAL "/= (T_DIVIDE_EQUAL)"
%token T_SET "set (T_SET)" %token T_VAR "var (T_VAR)"
%token T_CONST "const (T_CONST)"
%token T_SHIFT_LEFT "<< (T_SHIFT_LEFT)" %token T_SHIFT_LEFT "<< (T_SHIFT_LEFT)"
%token T_SHIFT_RIGHT ">> (T_SHIFT_RIGHT)" %token T_SHIFT_RIGHT ">> (T_SHIFT_RIGHT)"
%token <type> T_TYPE_DICTIONARY "dictionary (T_TYPE_DICTIONARY)" %token <type> T_TYPE_DICTIONARY "dictionary (T_TYPE_DICTIONARY)"
@ -113,6 +114,7 @@ using namespace icinga;
%type <slist> object_inherits_specifier %type <slist> object_inherits_specifier
%type <aexpr> aterm %type <aexpr> aterm
%type <aexpr> aexpression %type <aexpr> aexpression
%type <num> variable_decl
%left '+' '-' %left '+' '-'
%left '*' '/' %left '*' '/'
%left '&' %left '&'
@ -187,8 +189,9 @@ library: T_LIBRARY T_STRING
context->HandleLibrary($2); context->HandleLibrary($2);
free($2); free($2);
} }
;
variable: T_SET identifier T_EQUAL value variable: variable_decl identifier T_EQUAL value
{ {
Value *value = $4; Value *value = $4;
if (value->IsObjectType<ExpressionList>()) { if (value->IsObjectType<ExpressionList>()) {
@ -199,10 +202,25 @@ variable: T_SET identifier T_EQUAL value
value = new Value(dict); value = new Value(dict);
} }
ScriptVariable::Set($2, *value); ScriptVariable::Ptr sv = ScriptVariable::Set($2, *value);
if (!$1)
sv->SetConstant(true);
free($2); free($2);
delete value; delete value;
} }
;
variable_decl: T_VAR
{
$$ = true;
}
| T_CONST
{
$$ = false;
}
;
identifier: T_IDENTIFIER identifier: T_IDENTIFIER
| T_STRING | T_STRING