From d463bed478c16066fb79aa0e641808fcc7f59150 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 6 Feb 2013 00:32:05 +0100 Subject: [PATCH] Config: Implement detection of missing required attributes Fixes #3627 --- icinga-app/icinga.cpp | 21 +- itl/types.conf | 131 ++++---- lib/config/config_lexer.cc | 388 ++++++++++++----------- lib/config/config_lexer.ll | 3 + lib/config/config_parser.cc | 458 ++++++++++++++------------- lib/config/config_parser.h | 40 ++- lib/config/config_parser.yy | 27 +- lib/config/configcompilercontext.cpp | 15 +- lib/config/configcompilercontext.h | 4 + lib/config/configitem.cpp | 41 ++- lib/config/configitem.h | 6 +- lib/config/configitembuilder.cpp | 13 +- lib/config/configitembuilder.h | 2 + lib/config/configtype.cpp | 56 +++- lib/config/configtype.h | 1 + lib/config/typerulelist.cpp | 55 +++- lib/config/typerulelist.h | 11 +- lib/icinga/host.cpp | 17 + lib/icinga/host.h | 3 + 19 files changed, 780 insertions(+), 512 deletions(-) diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index 3f5f97836..41c938031 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -31,7 +31,7 @@ using namespace icinga; namespace po = boost::program_options; static po::variables_map g_AppParams; -static vector g_ConfigItems; +static String g_ConfigUnit; #ifndef _WIN32 static bool g_ReloadConfig = false; @@ -88,20 +88,15 @@ static bool LoadConfigFiles(bool validateOnly) context.ActivateItems(); - BOOST_FOREACH(const ConfigItem::WeakPtr& witem, g_ConfigItems) { - ConfigItem::Ptr item = witem.lock(); - - /* Ignore this item if it's not active anymore */ - if (!item || ConfigItem::GetObject(item->GetType(), item->GetName()) != item) - continue; - - item->Unregister(); + if (!g_ConfigUnit.IsEmpty()) { + /* ActivateItems has taken care of replacing all previous items + * with new versions - which are automatically in a different + * compilation unit. This UnloadUnit() call takes care of + * removing all left-over items from the previous config. */ + ConfigItem::UnloadUnit(g_ConfigUnit); } - g_ConfigItems.clear(); - - vector items = context.GetItems(); - std::copy(items.begin(), items.end(), std::back_inserter(g_ConfigItems)); + g_ConfigUnit = context.GetUnit(); return true; } diff --git a/itl/types.conf b/itl/types.conf index c09b80cad..8a41bf0a9 100644 --- a/itl/types.conf +++ b/itl/types.conf @@ -18,104 +18,119 @@ ******************************************************************************/ type DynamicObject { - number __abstract, - number __local, - string __name, - string __type, + %require "__abstract", + %attribute number "__abstract", - dictionary methods { - string *, + %require "__local", + %attribute number "__local", + + %require "__name", + %attribute string "__name", + + %require "__type", + %attribute string "__type", + + %attribute dictionary "methods" { + %attribute string "*", }, - any custom::* + %attribute any "custom::*" } type Component { } type Logger { - string "type", - string path, - string severity + %attribute string "type", + %attribute string "path", + %attribute string "severity" } type Host { - string alias, - dictionary hostgroups { - string * + %attribute string "alias", + %attribute dictionary "hostgroups" { + %attribute string "*" }, - dictionary dependencies { - string * + %attribute dictionary "dependencies" { + %attribute string "*" }, - dictionary hostchecks { - string * + %attribute dictionary "hostchecks" { + %attribute string "*" }, - dictionary services { - any * /* TODO: more specific validation rules */ + %attribute dictionary "services" { + %attribute any "*" /* TODO: more specific validation rules */ }, /* service attributes */ - number max_check_attempts, - number check_interval, - number retry_interval, - dictionary macros { - string * + %attribute number "max_check_attempts", + %attribute number "check_interval", + %attribute number "retry_interval", + %attribute dictionary "macros" { + %attribute string "*" }, - dictionary servicegroups { - string * + %attribute dictionary "servicegroups" { + %attribute string "*" }, - dictionary checkers { - string * + %attribute dictionary "checkers" { + %attribute string "*" } } type HostGroup { - string alias, - string notes_url, - string action_url + %attribute string "alias", + %attribute string "notes_url", + %attribute string "action_url" } type IcingaApplication { - string cert_path, - string ca_path, - string node, - string service, - string pid_path, - string state_path, - dictionary macros + %attribute string "cert_path", + %attribute string "ca_path", + %attribute string "node", + %attribute string "service", + %attribute string "pid_path", + %attribute string "state_path", + %attribute dictionary "macros" } type Service { - string alias, - string host_name, - dictionary macros { - string * + %require "host_name", + %attribute string "host_name", + + %attribute string "alias", + %attribute dictionary "macros" { + %attribute string "*" }, - string check_command, - number max_check_attempts, - number check_interval, - number retry_interval, - dictionary dependencies { - string * + %attribute string "check_command", + %attribute number "max_check_attempts", + %attribute number "check_interval", + %attribute number "retry_interval", + %attribute dictionary "dependencies" { + %attribute string "*" }, - dictionary servicegroups { - string * + %attribute dictionary "servicegroups" { + %attribute string "*" }, - dictionary checkers { - string * + %attribute dictionary "checkers" { + %attribute string "*" + }, + + %require "methods", + %attribute dictionary "methods" { + %require "check", + %attribute string "check" } } type ServiceGroup { - string alias, - string notes_url, - string action_url + %attribute string "alias", + %attribute string "notes_url", + %attribute string "action_url" } type Endpoint { - string node, - string service, - number "local" + %attribute string "node", + %attribute string "service", + %attribute number "local" } type TimePeriod { diff --git a/lib/config/config_lexer.cc b/lib/config/config_lexer.cc index 463ba091b..8b8bb86d2 100644 --- a/lib/config/config_lexer.cc +++ b/lib/config/config_lexer.cc @@ -370,8 +370,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 36 -#define YY_END_OF_BUFFER 37 +#define YY_NUM_RULES 39 +#define YY_END_OF_BUFFER 40 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -379,23 +379,25 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[134] = +static yyconst flex_int16_t yy_accept[160] = { 0, - 0, 0, 0, 0, 37, 35, 34, 34, 35, 35, - 17, 35, 35, 35, 23, 35, 24, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 31, 32, - 34, 0, 18, 0, 0, 17, 27, 25, 23, 26, - 29, 0, 28, 0, 20, 21, 22, 0, 19, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 31, 30, 0, 0, 33, 23, 17, 6, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 0, 0, 17, 17, 17, 17, 17, 13, - 17, 17, 17, 17, 17, 15, 1, 0, 0, 17, + 0, 0, 0, 0, 40, 38, 37, 37, 38, 38, + 38, 20, 38, 38, 38, 26, 38, 27, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 34, + 35, 37, 0, 21, 0, 0, 0, 0, 0, 20, + 30, 28, 26, 29, 32, 0, 31, 0, 23, 24, + 25, 0, 22, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 34, 33, 0, 0, + 0, 0, 0, 36, 26, 20, 6, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, + 0, 0, 0, 0, 20, 20, 20, 20, 20, 16, - 17, 16, 17, 8, 17, 17, 17, 17, 17, 0, - 0, 17, 17, 17, 3, 9, 17, 5, 4, 0, - 0, 17, 17, 17, 14, 10, 11, 7, 17, 12, - 17, 2, 0 + 20, 20, 20, 20, 20, 18, 1, 0, 0, 0, + 0, 0, 20, 20, 19, 20, 11, 20, 20, 20, + 20, 20, 0, 0, 0, 0, 0, 20, 20, 20, + 3, 12, 20, 5, 4, 0, 0, 0, 0, 0, + 20, 20, 20, 17, 13, 14, 0, 8, 0, 10, + 20, 15, 0, 0, 20, 9, 7, 2, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -403,17 +405,17 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 1, 4, 5, 1, 1, 1, 1, 1, - 1, 6, 7, 1, 8, 9, 10, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 12, 1, 13, - 14, 15, 1, 1, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 1, 1, 1, 1, 16, 1, 17, 18, 19, 20, + 1, 2, 1, 4, 5, 1, 6, 1, 1, 1, + 1, 7, 8, 1, 9, 10, 11, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 13, 1, 14, + 15, 16, 1, 1, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 1, 1, 1, 1, 17, 1, 18, 19, 20, 21, - 21, 22, 23, 24, 25, 26, 16, 27, 28, 29, - 30, 31, 16, 32, 33, 34, 35, 16, 16, 16, - 36, 16, 1, 1, 1, 1, 1, 1, 1, 1, + 22, 23, 24, 25, 26, 27, 17, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 17, 17, + 39, 17, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -430,127 +432,142 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[37] = +static yyconst flex_int32_t yy_meta[40] = { 0, - 1, 1, 2, 1, 1, 3, 1, 4, 1, 1, - 4, 4, 1, 4, 1, 4, 4, 4, 4, 4, + 1, 1, 2, 1, 1, 1, 3, 1, 4, 1, + 1, 4, 4, 1, 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4 + 4, 4, 4, 4, 4, 4, 4, 4, 4 } ; -static yyconst flex_int16_t yy_base[140] = +static yyconst flex_int16_t yy_base[166] = { 0, - 0, 0, 246, 245, 250, 253, 35, 37, 245, 16, - 234, 233, 31, 38, 38, 231, 253, 231, 32, 39, - 37, 41, 42, 43, 45, 51, 55, 44, 0, 234, - 79, 239, 253, 213, 216, 226, 253, 253, 64, 253, - 253, 0, 253, 228, 253, 253, 253, 223, 253, 46, - 63, 71, 69, 70, 72, 73, 79, 81, 89, 84, - 88, 90, 0, 253, 218, 218, 0, 96, 94, 221, - 96, 98, 97, 100, 95, 101, 111, 112, 113, 119, - 120, 121, 207, 199, 122, 123, 124, 125, 129, 214, - 137, 133, 135, 136, 141, 196, 195, 173, 190, 145, + 0, 0, 273, 272, 278, 281, 38, 40, 273, 18, + 27, 261, 260, 35, 41, 39, 258, 281, 258, 39, + 40, 42, 47, 44, 48, 52, 55, 61, 57, 0, + 261, 76, 267, 281, 240, 243, 232, 245, 248, 250, + 281, 281, 70, 281, 281, 0, 281, 252, 281, 281, + 281, 247, 281, 68, 69, 72, 73, 75, 74, 78, + 71, 87, 94, 89, 95, 96, 0, 281, 242, 242, + 224, 226, 230, 0, 101, 99, 242, 101, 103, 100, + 102, 112, 110, 109, 118, 119, 124, 126, 127, 228, + 221, 220, 216, 226, 128, 129, 130, 131, 136, 236, - 147, 192, 149, 191, 150, 151, 152, 154, 153, 184, - 171, 159, 158, 157, 187, 184, 161, 183, 182, 174, - 158, 165, 166, 167, 179, 253, 253, 178, 170, 176, - 175, 53, 253, 211, 215, 217, 221, 225, 229 + 138, 141, 142, 148, 143, 235, 234, 211, 229, 220, + 219, 223, 152, 144, 228, 154, 227, 156, 157, 159, + 161, 163, 220, 206, 220, 202, 215, 164, 166, 167, + 200, 199, 170, 198, 197, 189, 170, 170, 184, 169, + 168, 171, 173, 187, 281, 281, 165, 281, 169, 184, + 176, 182, 172, 85, 177, 281, 281, 38, 281, 216, + 220, 222, 226, 230, 234 } ; -static yyconst flex_int16_t yy_def[140] = +static yyconst flex_int16_t yy_def[166] = { 0, - 133, 1, 134, 134, 133, 133, 133, 133, 135, 133, - 136, 133, 133, 133, 133, 137, 133, 136, 136, 136, - 136, 136, 136, 136, 136, 136, 136, 136, 138, 133, - 133, 135, 133, 133, 133, 136, 133, 133, 133, 133, - 133, 139, 133, 133, 133, 133, 133, 137, 133, 136, - 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, - 136, 136, 138, 133, 133, 133, 139, 133, 136, 136, - 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, - 136, 136, 133, 133, 136, 136, 136, 136, 136, 136, - 136, 136, 136, 136, 136, 136, 136, 133, 133, 136, + 159, 1, 160, 160, 159, 159, 159, 159, 161, 159, + 159, 162, 159, 159, 159, 159, 163, 159, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 164, + 159, 159, 161, 159, 159, 159, 159, 159, 159, 162, + 159, 159, 159, 159, 159, 165, 159, 159, 159, 159, + 159, 163, 159, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 164, 159, 159, 159, + 159, 159, 159, 165, 159, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 159, + 159, 159, 159, 159, 162, 162, 162, 162, 162, 162, - 136, 136, 136, 136, 136, 136, 136, 136, 136, 133, - 133, 136, 136, 136, 136, 136, 136, 136, 136, 133, - 133, 136, 136, 136, 136, 133, 133, 136, 136, 136, - 136, 136, 0, 133, 133, 133, 133, 133, 133 + 162, 162, 162, 162, 162, 162, 162, 159, 159, 159, + 159, 159, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 159, 159, 159, 159, 159, 162, 162, 162, + 162, 162, 162, 162, 162, 159, 159, 159, 159, 159, + 162, 162, 162, 162, 159, 159, 159, 159, 159, 162, + 162, 162, 159, 159, 162, 159, 159, 162, 0, 159, + 159, 159, 159, 159, 159 } ; -static yyconst flex_int16_t yy_nxt[290] = +static yyconst flex_int16_t yy_nxt[321] = { 0, - 6, 7, 8, 9, 10, 11, 12, 13, 6, 14, - 15, 6, 16, 17, 6, 18, 19, 18, 18, 20, - 18, 21, 18, 18, 22, 18, 23, 18, 24, 25, - 26, 18, 27, 28, 18, 18, 31, 31, 31, 31, - 34, 39, 35, 41, 40, 133, 44, 42, 39, 50, - 133, 43, 133, 53, 133, 133, 133, 133, 133, 133, - 51, 45, 57, 52, 133, 46, 133, 58, 133, 54, - 47, 55, 44, 59, 39, 61, 133, 56, 69, 62, - 31, 31, 133, 133, 133, 133, 133, 45, 60, 71, - 74, 46, 133, 73, 133, 72, 47, 133, 70, 75, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 6, + 15, 16, 6, 17, 18, 6, 19, 20, 19, 19, + 21, 19, 22, 19, 19, 23, 19, 24, 19, 25, + 26, 27, 19, 19, 28, 29, 19, 19, 19, 32, + 32, 32, 32, 35, 37, 36, 43, 45, 48, 44, + 43, 46, 159, 159, 159, 47, 159, 54, 159, 57, + 38, 159, 159, 49, 39, 56, 159, 50, 55, 159, + 61, 159, 62, 51, 59, 159, 58, 32, 32, 48, + 63, 43, 159, 159, 60, 159, 159, 159, 159, 159, + 65, 78, 159, 81, 49, 66, 64, 84, 50, 80, - 76, 133, 133, 133, 77, 79, 68, 133, 133, 133, - 133, 133, 78, 133, 133, 80, 89, 88, 91, 45, - 82, 90, 81, 46, 133, 133, 133, 85, 47, 86, - 87, 92, 133, 133, 133, 133, 133, 133, 133, 94, - 96, 97, 133, 95, 102, 93, 133, 101, 133, 133, - 133, 106, 108, 100, 133, 104, 103, 105, 133, 107, - 133, 112, 133, 133, 133, 133, 133, 133, 117, 109, - 133, 133, 133, 114, 133, 119, 113, 122, 133, 133, - 133, 115, 129, 133, 116, 118, 123, 125, 133, 133, - 124, 133, 133, 127, 126, 133, 133, 133, 128, 130, + 79, 159, 76, 159, 51, 82, 83, 77, 159, 159, + 159, 86, 75, 159, 159, 159, 159, 159, 157, 99, + 85, 98, 87, 159, 159, 49, 159, 89, 101, 50, + 102, 88, 159, 159, 95, 51, 96, 97, 159, 100, + 159, 159, 159, 159, 159, 159, 104, 106, 107, 105, + 159, 115, 159, 103, 114, 159, 159, 159, 159, 118, + 119, 113, 159, 117, 116, 121, 159, 120, 159, 128, + 159, 159, 122, 159, 129, 159, 133, 159, 159, 130, + 159, 159, 159, 141, 159, 159, 135, 159, 151, 131, + 159, 159, 132, 156, 134, 142, 159, 144, 159, 154, - 133, 131, 121, 120, 133, 133, 111, 110, 133, 133, - 132, 29, 29, 29, 29, 32, 32, 32, 32, 36, - 36, 48, 48, 48, 48, 63, 63, 133, 63, 67, - 99, 67, 67, 98, 133, 84, 83, 49, 68, 133, - 66, 65, 33, 64, 133, 49, 38, 37, 33, 133, - 30, 30, 5, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133 + 153, 159, 143, 150, 149, 148, 147, 152, 146, 155, + 145, 159, 159, 159, 159, 158, 30, 30, 30, 30, + 33, 33, 33, 33, 40, 40, 52, 52, 52, 52, + 67, 67, 140, 67, 74, 139, 74, 74, 138, 137, + 136, 159, 159, 127, 126, 125, 124, 123, 159, 159, + 159, 112, 111, 110, 109, 108, 159, 94, 93, 92, + 91, 90, 53, 75, 159, 73, 72, 71, 70, 69, + 34, 68, 159, 53, 42, 41, 34, 159, 31, 31, + 5, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159 } ; -static yyconst flex_int16_t yy_chk[290] = +static yyconst flex_int16_t yy_chk[321] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 7, 7, 8, 8, - 10, 13, 10, 14, 13, 19, 15, 14, 15, 19, - 21, 14, 20, 21, 22, 23, 24, 28, 25, 50, - 19, 15, 25, 20, 26, 15, 132, 26, 27, 22, - 15, 23, 39, 27, 39, 28, 51, 24, 50, 28, - 31, 31, 53, 54, 52, 55, 56, 39, 27, 52, - 55, 39, 57, 54, 58, 53, 39, 60, 51, 56, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, + 7, 8, 8, 10, 11, 10, 14, 15, 16, 14, + 16, 15, 158, 20, 21, 15, 22, 20, 24, 22, + 11, 23, 25, 16, 11, 21, 26, 16, 20, 27, + 26, 29, 27, 16, 24, 28, 23, 32, 32, 43, + 28, 43, 54, 55, 25, 61, 56, 57, 59, 58, + 29, 56, 60, 59, 43, 29, 28, 61, 43, 58, - 56, 61, 59, 62, 57, 59, 68, 69, 75, 71, - 73, 72, 58, 74, 76, 60, 74, 73, 76, 68, - 62, 75, 61, 68, 77, 78, 79, 69, 68, 71, - 72, 77, 80, 81, 82, 85, 86, 87, 88, 79, - 81, 82, 89, 80, 87, 78, 92, 86, 93, 94, - 91, 92, 94, 85, 95, 89, 88, 91, 100, 93, - 101, 100, 103, 105, 106, 107, 109, 108, 107, 95, - 114, 113, 112, 103, 117, 109, 101, 112, 122, 123, - 124, 105, 123, 129, 106, 108, 113, 117, 131, 130, - 114, 128, 125, 121, 120, 119, 118, 116, 122, 124, + 57, 62, 54, 64, 43, 60, 60, 55, 63, 65, + 66, 63, 75, 76, 80, 78, 81, 79, 154, 81, + 62, 80, 64, 84, 83, 75, 82, 66, 83, 75, + 84, 65, 85, 86, 76, 75, 78, 79, 87, 82, + 88, 89, 95, 96, 97, 98, 86, 88, 89, 87, + 99, 97, 101, 85, 96, 102, 103, 105, 114, 101, + 102, 95, 104, 99, 98, 104, 113, 103, 116, 113, + 118, 119, 105, 120, 114, 121, 120, 122, 128, 116, + 129, 130, 141, 128, 133, 142, 122, 143, 142, 118, + 151, 155, 119, 153, 121, 129, 152, 133, 150, 149, - 115, 129, 111, 110, 104, 102, 99, 98, 97, 96, - 131, 134, 134, 134, 134, 135, 135, 135, 135, 136, - 136, 137, 137, 137, 137, 138, 138, 90, 138, 139, - 84, 139, 139, 83, 70, 66, 65, 48, 44, 36, - 35, 34, 32, 30, 18, 16, 12, 11, 9, 5, - 4, 3, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133 + 147, 144, 130, 141, 140, 139, 138, 143, 137, 151, + 136, 135, 134, 132, 131, 155, 160, 160, 160, 160, + 161, 161, 161, 161, 162, 162, 163, 163, 163, 163, + 164, 164, 127, 164, 165, 126, 165, 165, 125, 124, + 123, 117, 115, 112, 111, 110, 109, 108, 107, 106, + 100, 94, 93, 92, 91, 90, 77, 73, 72, 71, + 70, 69, 52, 48, 40, 39, 38, 37, 36, 35, + 33, 31, 19, 17, 13, 12, 9, 5, 4, 3, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159 } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[37] = +static yyconst flex_int32_t yy_rule_can_match_eol[40] = { 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, }; +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, + }; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. @@ -602,7 +619,7 @@ do { \ } while (0) #define YY_NO_UNISTD_H 1 -#line 606 "config_lexer.cc" +#line 623 "config_lexer.cc" #define INITIAL 0 #define IN_C_COMMENT 1 @@ -851,7 +868,7 @@ YY_DECL #line 49 "config_lexer.ll" -#line 855 "config_lexer.cc" +#line 872 "config_lexer.cc" yylval = yylval_param; @@ -908,13 +925,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 134 ) + if ( yy_current_state >= 160 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_current_state != 133 ); + while ( yy_current_state != 159 ); yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; @@ -979,162 +996,177 @@ YY_RULE_SETUP case 7: YY_RULE_SETUP #line 56 "config_lexer.ll" -return T_ABSTRACT; +{ return T_VALIDATOR; } YY_BREAK case 8: YY_RULE_SETUP #line 57 "config_lexer.ll" -return T_LOCAL; +{ return T_REQUIRE; } YY_BREAK case 9: YY_RULE_SETUP #line 58 "config_lexer.ll" -return T_OBJECT; +{ return T_ATTRIBUTE; } YY_BREAK case 10: YY_RULE_SETUP #line 59 "config_lexer.ll" -return T_INCLUDE; +return T_ABSTRACT; YY_BREAK case 11: YY_RULE_SETUP #line 60 "config_lexer.ll" -return T_LIBRARY; +return T_LOCAL; YY_BREAK case 12: YY_RULE_SETUP #line 61 "config_lexer.ll" -return T_INHERITS; +return T_OBJECT; YY_BREAK case 13: YY_RULE_SETUP #line 62 "config_lexer.ll" -return T_NULL; +return T_INCLUDE; YY_BREAK case 14: YY_RULE_SETUP #line 63 "config_lexer.ll" -return T_PARTIAL; +return T_LIBRARY; YY_BREAK case 15: YY_RULE_SETUP #line 64 "config_lexer.ll" -{ yylval->num = 1; return T_NUMBER; } +return T_INHERITS; YY_BREAK case 16: YY_RULE_SETUP #line 65 "config_lexer.ll" -{ yylval->num = 0; return T_NUMBER; } +return T_NULL; YY_BREAK case 17: YY_RULE_SETUP #line 66 "config_lexer.ll" -{ yylval->text = strdup(yytext); return T_IDENTIFIER; } +return T_PARTIAL; YY_BREAK case 18: -/* rule 18 can match eol */ YY_RULE_SETUP #line 67 "config_lexer.ll" -{ yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING; } +{ yylval->num = 1; return T_NUMBER; } YY_BREAK case 19: -/* rule 19 can match eol */ YY_RULE_SETUP #line 68 "config_lexer.ll" -{ yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING_ANGLE; } +{ yylval->num = 0; return T_NUMBER; } YY_BREAK case 20: YY_RULE_SETUP #line 69 "config_lexer.ll" -{ yylval->num = strtod(yytext, NULL) * 60 * 60; return T_NUMBER; } +{ yylval->text = strdup(yytext); return T_IDENTIFIER; } YY_BREAK case 21: +/* rule 21 can match eol */ YY_RULE_SETUP #line 70 "config_lexer.ll" -{ yylval->num = strtod(yytext, NULL) * 60; return T_NUMBER; } +{ yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING; } YY_BREAK case 22: +/* rule 22 can match eol */ YY_RULE_SETUP #line 71 "config_lexer.ll" -{ yylval->num = strtod(yytext, NULL); return T_NUMBER; } +{ yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING_ANGLE; } YY_BREAK case 23: YY_RULE_SETUP #line 72 "config_lexer.ll" -{ yylval->num = strtod(yytext, NULL); return T_NUMBER; } +{ yylval->num = strtod(yytext, NULL) * 60 * 60; return T_NUMBER; } YY_BREAK case 24: YY_RULE_SETUP #line 73 "config_lexer.ll" -{ yylval->op = OperatorSet; return T_EQUAL; } +{ yylval->num = strtod(yytext, NULL) * 60; return T_NUMBER; } YY_BREAK case 25: YY_RULE_SETUP #line 74 "config_lexer.ll" -{ yylval->op = OperatorPlus; return T_PLUS_EQUAL; } +{ yylval->num = strtod(yytext, NULL); return T_NUMBER; } YY_BREAK case 26: YY_RULE_SETUP #line 75 "config_lexer.ll" -{ yylval->op = OperatorMinus; return T_MINUS_EQUAL; } +{ yylval->num = strtod(yytext, NULL); return T_NUMBER; } YY_BREAK case 27: YY_RULE_SETUP #line 76 "config_lexer.ll" -{ yylval->op = OperatorMultiply; return T_MULTIPLY_EQUAL; } +{ yylval->op = OperatorSet; return T_EQUAL; } YY_BREAK case 28: YY_RULE_SETUP #line 77 "config_lexer.ll" +{ yylval->op = OperatorPlus; return T_PLUS_EQUAL; } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 78 "config_lexer.ll" +{ yylval->op = OperatorMinus; return T_MINUS_EQUAL; } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 79 "config_lexer.ll" +{ yylval->op = OperatorMultiply; return T_MULTIPLY_EQUAL; } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 80 "config_lexer.ll" { yylval->op = OperatorDivide; return T_DIVIDE_EQUAL; } YY_BREAK -case 29: +case 32: YY_RULE_SETUP -#line 80 "config_lexer.ll" +#line 83 "config_lexer.ll" BEGIN(IN_C_COMMENT); YY_BREAK -case 30: -YY_RULE_SETUP -#line 84 "config_lexer.ll" -BEGIN(INITIAL); - YY_BREAK -case 31: -/* rule 31 can match eol */ -YY_RULE_SETUP -#line 85 "config_lexer.ll" -/* ignore comment */ - YY_BREAK -case 32: -YY_RULE_SETUP -#line 86 "config_lexer.ll" -/* ignore star */ - YY_BREAK - case 33: YY_RULE_SETUP -#line 89 "config_lexer.ll" -/* ignore C++-style comments */ +#line 87 "config_lexer.ll" +BEGIN(INITIAL); YY_BREAK case 34: /* rule 34 can match eol */ YY_RULE_SETUP -#line 90 "config_lexer.ll" -/* ignore whitespace */ +#line 88 "config_lexer.ll" +/* ignore comment */ YY_BREAK case 35: YY_RULE_SETUP -#line 92 "config_lexer.ll" -return yytext[0]; +#line 89 "config_lexer.ll" +/* ignore star */ YY_BREAK + case 36: YY_RULE_SETUP +#line 92 "config_lexer.ll" +/* ignore C++-style comments */ + YY_BREAK +case 37: +/* rule 37 can match eol */ +YY_RULE_SETUP #line 93 "config_lexer.ll" +/* ignore whitespace */ + YY_BREAK +case 38: +YY_RULE_SETUP +#line 95 "config_lexer.ll" +return yytext[0]; + YY_BREAK +case 39: +YY_RULE_SETUP +#line 96 "config_lexer.ll" ECHO; YY_BREAK -#line 1138 "config_lexer.cc" +#line 1170 "config_lexer.cc" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(IN_C_COMMENT): yyterminate(); @@ -1430,7 +1462,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 134 ) + if ( yy_current_state >= 160 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1459,11 +1491,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 134 ) + if ( yy_current_state >= 160 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 133); + yy_is_jam = (yy_current_state == 159); return yy_is_jam ? 0 : yy_current_state; } @@ -2322,7 +2354,7 @@ void yyfree (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 93 "config_lexer.ll" +#line 96 "config_lexer.ll" diff --git a/lib/config/config_lexer.ll b/lib/config/config_lexer.ll index a94bd280e..00b5fc7d5 100644 --- a/lib/config/config_lexer.ll +++ b/lib/config/config_lexer.ll @@ -53,6 +53,9 @@ number { yylval->type = TypeNumber; return T_TYPE_NUMBER; } string { yylval->type = TypeString; return T_TYPE_STRING; } scalar { yylval->type = TypeScalar; return T_TYPE_SCALAR; } any { yylval->type = TypeAny; return T_TYPE_ANY; } +%validator { return T_VALIDATOR; } +%require { return T_REQUIRE; } +%attribute { return T_ATTRIBUTE; } abstract return T_ABSTRACT; local return T_LOCAL; object return T_OBJECT; diff --git a/lib/config/config_parser.cc b/lib/config/config_parser.cc index 461744fdd..308597e95 100644 --- a/lib/config/config_parser.cc +++ b/lib/config/config_parser.cc @@ -144,14 +144,17 @@ using namespace icinga; T_TYPE_STRING = 270, T_TYPE_SCALAR = 271, T_TYPE_ANY = 272, - T_TYPE = 273, - T_ABSTRACT = 274, - T_LOCAL = 275, - T_OBJECT = 276, - T_INCLUDE = 277, - T_LIBRARY = 278, - T_INHERITS = 279, - T_PARTIAL = 280 + T_VALIDATOR = 273, + T_REQUIRE = 274, + T_ATTRIBUTE = 275, + T_TYPE = 276, + T_ABSTRACT = 277, + T_LOCAL = 278, + T_OBJECT = 279, + T_INCLUDE = 280, + T_LIBRARY = 281, + T_INHERITS = 282, + T_PARTIAL = 283 }; #endif /* Tokens. */ @@ -170,14 +173,17 @@ using namespace icinga; #define T_TYPE_STRING 270 #define T_TYPE_SCALAR 271 #define T_TYPE_ANY 272 -#define T_TYPE 273 -#define T_ABSTRACT 274 -#define T_LOCAL 275 -#define T_OBJECT 276 -#define T_INCLUDE 277 -#define T_LIBRARY 278 -#define T_INHERITS 279 -#define T_PARTIAL 280 +#define T_VALIDATOR 273 +#define T_REQUIRE 274 +#define T_ATTRIBUTE 275 +#define T_TYPE 276 +#define T_ABSTRACT 277 +#define T_LOCAL 278 +#define T_OBJECT 279 +#define T_INCLUDE 280 +#define T_LIBRARY 281 +#define T_INHERITS 282 +#define T_PARTIAL 283 @@ -198,7 +204,7 @@ typedef union YYSTYPE /* Line 293 of yacc.c */ -#line 202 "config_parser.cc" +#line 208 "config_parser.cc" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -222,7 +228,7 @@ typedef struct YYLTYPE /* Copy the second part of user declarations. */ /* Line 343 of yacc.c */ -#line 79 "config_parser.yy" +#line 82 "config_parser.yy" int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner); @@ -260,7 +266,7 @@ void ConfigCompiler::Compile(void) /* Line 343 of yacc.c */ -#line 264 "config_parser.cc" +#line 270 "config_parser.cc" #ifdef short # undef short @@ -481,20 +487,20 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 80 +#define YYLAST 76 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 35 +#define YYNTOKENS 38 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 31 /* YYNRULES -- Number of rules. */ -#define YYNRULES 64 +#define YYNRULES 66 /* YYNRULES -- Number of states. */ -#define YYNSTATES 84 +#define YYNSTATES 89 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 280 +#define YYMAXUTOK 283 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -506,15 +512,15 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 28, 26, 32, 27, 2, 29, 2, 2, + 2, 2, 31, 29, 35, 30, 2, 32, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 33, 2, 34, 2, 2, 2, 2, 2, 2, + 2, 36, 2, 37, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 30, 2, 31, 2, 2, 2, 2, + 2, 2, 2, 33, 2, 34, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -530,7 +536,7 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25 + 25, 26, 27, 28 }; #if YYDEBUG @@ -540,44 +546,45 @@ static const yytype_uint8 yyprhs[] = { 0, 0, 3, 4, 7, 9, 11, 13, 15, 18, 21, 24, 26, 28, 29, 36, 37, 39, 40, 45, - 47, 50, 51, 53, 57, 60, 64, 65, 68, 70, - 72, 74, 76, 78, 79, 80, 89, 90, 93, 95, - 97, 99, 103, 105, 106, 109, 110, 115, 117, 120, - 121, 123, 127, 131, 138, 140, 142, 144, 146, 148, - 150, 152, 154, 156, 158 + 47, 50, 51, 53, 57, 60, 63, 67, 72, 73, + 76, 78, 80, 82, 84, 86, 87, 88, 97, 98, + 101, 103, 105, 107, 111, 113, 114, 117, 118, 123, + 125, 128, 129, 131, 135, 139, 146, 148, 150, 152, + 154, 156, 158, 160, 162, 164, 166 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 36, 0, -1, -1, 36, 37, -1, 50, -1, 41, - -1, 38, -1, 39, -1, 22, 3, -1, 22, 4, - -1, 23, 3, -1, 7, -1, 3, -1, -1, 43, - 18, 40, 42, 49, 44, -1, -1, 25, -1, -1, - 30, 45, 46, 31, -1, 47, -1, 47, 32, -1, - -1, 48, -1, 47, 32, 48, -1, 41, 40, -1, - 41, 40, 44, -1, -1, 24, 3, -1, 13, -1, - 14, -1, 15, -1, 16, -1, 17, -1, -1, -1, - 51, 53, 21, 40, 3, 52, 57, 58, -1, -1, - 53, 54, -1, 19, -1, 20, -1, 56, -1, 55, - 32, 56, -1, 3, -1, -1, 24, 55, -1, -1, - 30, 59, 60, 31, -1, 61, -1, 61, 32, -1, - -1, 62, -1, 61, 32, 62, -1, 40, 63, 65, - -1, 40, 33, 3, 34, 63, 65, -1, 3, -1, - 8, -1, 9, -1, 10, -1, 11, -1, 12, -1, - 3, -1, 5, -1, 6, -1, 64, -1, 58, -1 + 39, 0, -1, -1, 39, 40, -1, 53, -1, 44, + -1, 41, -1, 42, -1, 25, 3, -1, 25, 4, + -1, 26, 3, -1, 7, -1, 3, -1, -1, 46, + 21, 43, 45, 52, 47, -1, -1, 28, -1, -1, + 33, 48, 49, 34, -1, 50, -1, 50, 35, -1, + -1, 51, -1, 50, 35, 51, -1, 19, 3, -1, + 18, 3, -1, 20, 44, 3, -1, 20, 44, 3, + 47, -1, -1, 27, 3, -1, 13, -1, 14, -1, + 15, -1, 16, -1, 17, -1, -1, -1, 54, 56, + 24, 43, 3, 55, 60, 61, -1, -1, 56, 57, + -1, 22, -1, 23, -1, 59, -1, 58, 35, 59, + -1, 3, -1, -1, 27, 58, -1, -1, 33, 62, + 63, 34, -1, 64, -1, 64, 35, -1, -1, 65, + -1, 64, 35, 65, -1, 43, 66, 68, -1, 43, + 36, 3, 37, 66, 68, -1, 3, -1, 8, -1, + 9, -1, 10, -1, 11, -1, 12, -1, 3, -1, + 5, -1, 6, -1, 67, -1, 61, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 116, 116, 117, 120, 120, 120, 120, 123, 127, - 132, 137, 138, 145, 144, 166, 169, 176, 175, 187, - 188, 190, 191, 192, 195, 200, 208, 209, 215, 216, - 217, 218, 219, 226, 231, 226, 250, 251, 254, 258, - 264, 265, 268, 275, 276, 280, 279, 291, 292, 294, - 295, 296, 299, 307, 321, 330, 331, 332, 333, 334, - 340, 345, 349, 355, 356 + 0, 119, 119, 120, 123, 123, 123, 123, 126, 130, + 135, 140, 141, 148, 147, 175, 178, 185, 184, 196, + 197, 199, 200, 201, 204, 208, 212, 217, 225, 226, + 232, 233, 234, 235, 236, 243, 248, 243, 267, 268, + 271, 275, 281, 282, 285, 292, 293, 297, 296, 308, + 309, 311, 312, 313, 316, 324, 338, 347, 348, 349, + 350, 351, 357, 362, 366, 372, 373 }; #endif @@ -590,13 +597,14 @@ static const char *const yytname[] = "T_NULL", "T_IDENTIFIER", "T_EQUAL", "T_PLUS_EQUAL", "T_MINUS_EQUAL", "T_MULTIPLY_EQUAL", "T_DIVIDE_EQUAL", "T_TYPE_DICTIONARY", "T_TYPE_NUMBER", "T_TYPE_STRING", "T_TYPE_SCALAR", "T_TYPE_ANY", - "T_TYPE", "T_ABSTRACT", "T_LOCAL", "T_OBJECT", "T_INCLUDE", "T_LIBRARY", - "T_INHERITS", "T_PARTIAL", "'+'", "'-'", "'*'", "'/'", "'{'", "'}'", - "','", "'['", "']'", "$accept", "statements", "statement", "include", - "library", "identifier", "type", "$@1", "partial_specifier", - "typerulelist", "$@2", "typerules", "typerules_inner", "typerule", - "type_inherits_specifier", "object", "$@3", "$@4", "attributes", - "attribute", "object_inherits_list", "object_inherits_item", + "T_VALIDATOR", "T_REQUIRE", "T_ATTRIBUTE", "T_TYPE", "T_ABSTRACT", + "T_LOCAL", "T_OBJECT", "T_INCLUDE", "T_LIBRARY", "T_INHERITS", + "T_PARTIAL", "'+'", "'-'", "'*'", "'/'", "'{'", "'}'", "','", "'['", + "']'", "$accept", "statements", "statement", "include", "library", + "identifier", "type", "$@1", "partial_specifier", "typerulelist", "$@2", + "typerules", "typerules_inner", "typerule", "type_inherits_specifier", + "object", "$@3", "$@4", "attributes", "attribute", + "object_inherits_list", "object_inherits_item", "object_inherits_specifier", "expressionlist", "$@5", "expressions", "expressions_inner", "expression", "operator", "simplevalue", "value", 0 }; @@ -609,21 +617,21 @@ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 43, 45, 42, 47, - 123, 125, 44, 91, 93 + 275, 276, 277, 278, 279, 280, 281, 282, 283, 43, + 45, 42, 47, 123, 125, 44, 91, 93 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 35, 36, 36, 37, 37, 37, 37, 38, 38, - 39, 40, 40, 42, 41, 43, 43, 45, 44, 46, - 46, 47, 47, 47, 48, 48, 49, 49, 41, 41, - 41, 41, 41, 51, 52, 50, 53, 53, 54, 54, - 55, 55, 56, 57, 57, 59, 58, 60, 60, 61, - 61, 61, 62, 62, 62, 63, 63, 63, 63, 63, - 64, 64, 64, 65, 65 + 0, 38, 39, 39, 40, 40, 40, 40, 41, 41, + 42, 43, 43, 45, 44, 46, 46, 48, 47, 49, + 49, 50, 50, 50, 51, 51, 51, 51, 52, 52, + 44, 44, 44, 44, 44, 54, 55, 53, 56, 56, + 57, 57, 58, 58, 59, 60, 60, 62, 61, 63, + 63, 64, 64, 64, 65, 65, 65, 66, 66, 66, + 66, 66, 67, 67, 67, 68, 68 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -631,11 +639,11 @@ static const yytype_uint8 yyr2[] = { 0, 2, 0, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, 0, 6, 0, 1, 0, 4, 1, - 2, 0, 1, 3, 2, 3, 0, 2, 1, 1, - 1, 1, 1, 0, 0, 8, 0, 2, 1, 1, - 1, 3, 1, 0, 2, 0, 4, 1, 2, 0, - 1, 3, 3, 6, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 + 2, 0, 1, 3, 2, 2, 3, 4, 0, 2, + 1, 1, 1, 1, 1, 0, 0, 8, 0, 2, + 1, 1, 1, 3, 1, 0, 2, 0, 4, 1, + 2, 0, 1, 3, 3, 6, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. @@ -643,100 +651,98 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 2, 33, 1, 28, 29, 30, 31, 32, 0, 0, - 16, 3, 6, 7, 5, 0, 4, 36, 8, 9, - 10, 0, 0, 12, 11, 13, 38, 39, 0, 37, - 26, 0, 0, 0, 34, 27, 17, 14, 43, 21, - 0, 0, 0, 0, 19, 22, 42, 44, 40, 45, - 35, 24, 18, 15, 0, 49, 25, 23, 41, 12, - 0, 0, 47, 50, 55, 56, 57, 58, 59, 0, - 0, 46, 48, 0, 60, 61, 62, 64, 63, 52, - 51, 0, 0, 53 + 2, 35, 1, 30, 31, 32, 33, 34, 0, 0, + 16, 3, 6, 7, 5, 0, 4, 38, 8, 9, + 10, 0, 0, 12, 11, 13, 40, 41, 0, 39, + 28, 0, 0, 0, 36, 29, 17, 14, 45, 21, + 0, 0, 0, 0, 15, 0, 19, 22, 44, 46, + 42, 47, 37, 25, 24, 0, 18, 20, 0, 51, + 26, 23, 43, 12, 0, 0, 49, 52, 27, 57, + 58, 59, 60, 61, 0, 0, 48, 50, 0, 62, + 63, 64, 66, 65, 54, 53, 0, 0, 55 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 1, 11, 12, 13, 60, 42, 30, 15, 37, - 39, 43, 44, 45, 33, 16, 17, 38, 22, 29, - 47, 48, 41, 77, 55, 61, 62, 63, 70, 78, - 79 + -1, 1, 11, 12, 13, 64, 14, 30, 15, 37, + 39, 45, 46, 47, 33, 16, 17, 38, 22, 29, + 49, 50, 41, 82, 59, 65, 66, 67, 75, 83, + 84 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -12 +#define YYPACT_NINF -17 static const yytype_int8 yypact[] = { - -12, 1, -12, -12, -12, -12, -12, -12, 45, 9, - -12, -12, -12, -12, -12, 4, -12, -12, -12, -12, - -12, 18, -10, -12, -12, -12, -12, -12, 18, -12, - 26, 30, 43, 21, -12, -12, -12, -12, 35, 27, - 57, 31, 18, 32, 33, -12, -12, 34, -12, -12, - -12, 21, -12, 22, 57, 25, -12, -12, -12, -1, - -4, 36, 37, -12, -12, -12, -12, -12, -12, 59, - -3, -12, 25, 38, -12, -12, -12, -12, -12, -12, - -12, 46, -3, -12 + -17, 1, -17, -17, -17, -17, -17, -17, 7, 18, + -17, -17, -17, -17, -17, 2, -17, -17, -17, -17, + -17, 6, 21, -17, -17, -17, -17, -17, 6, -17, + -2, 25, 28, 19, -17, -17, -17, -17, 26, 31, + 51, 22, 53, 54, 20, 24, 27, -17, -17, 29, + -17, -17, -17, -17, -17, 56, -17, 31, 51, 17, + 19, -17, -17, 12, -4, 32, 33, -17, -17, -17, + -17, -17, -17, -17, 57, -3, -17, 17, 34, -17, + -17, -17, -17, -17, -17, -17, 30, -3, -17 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -12, -12, -12, -12, -12, -8, 63, -12, -12, 17, - -12, -12, -12, 20, -12, -12, -12, -12, -12, -12, - -12, 16, -12, 39, -12, -12, -12, 2, -6, -12, - -11 + -17, -17, -17, -17, -17, -9, 23, -17, -17, 3, + -17, -17, -17, 4, -17, -17, -17, -17, -17, -17, + -17, 11, -17, 35, -17, -17, -17, -12, -16, -17, + -15 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -55 +#define YYTABLE_NINF -57 static const yytype_int8 yytable[] = { - 74, 2, 75, 76, 64, 65, 66, 67, 68, 26, - 27, 28, 20, 25, 3, 4, 5, 6, 7, -15, - 31, 23, 21, 8, 9, 24, 10, 49, 59, 69, - -54, -54, 24, 34, 51, 3, 4, 5, 6, 7, - 3, 4, 5, 6, 7, -15, 35, 10, 18, 19, - 32, 36, 10, -20, 64, 65, 66, 67, 68, 40, - 46, 49, 73, 52, 14, 53, 54, 71, 56, 72, - 58, 83, 81, 57, 80, 82, 0, 0, 0, 0, - 50 + 79, 2, 80, 81, 69, 70, 71, 72, 73, 23, + 18, 19, 25, 24, 3, 4, 5, 6, 7, 31, + 63, 20, -15, 21, 24, 32, 8, 9, 34, 10, + 51, 35, 74, 3, 4, 5, 6, 7, 69, 70, + 71, 72, 73, 26, 27, 28, -56, -56, 10, 42, + 43, 44, 36, 40, 48, 51, 53, 54, 56, 60, + 78, 61, 57, 68, 58, 85, 76, 55, 77, 62, + 87, 86, 88, 0, 0, 0, 52 }; #define yypact_value_is_default(yystate) \ - ((yystate) == (-12)) + ((yystate) == (-17)) #define yytable_value_is_error(yytable_value) \ YYID (0) static const yytype_int8 yycheck[] = { - 3, 0, 5, 6, 8, 9, 10, 11, 12, 19, - 20, 21, 3, 21, 13, 14, 15, 16, 17, 18, - 28, 3, 18, 22, 23, 7, 25, 30, 3, 33, - 31, 32, 7, 3, 42, 13, 14, 15, 16, 17, - 13, 14, 15, 16, 17, 18, 3, 25, 3, 4, - 24, 30, 25, 31, 8, 9, 10, 11, 12, 24, - 3, 30, 3, 31, 1, 32, 32, 31, 51, 32, - 54, 82, 34, 53, 72, 81, -1, -1, -1, -1, - 41 + 3, 0, 5, 6, 8, 9, 10, 11, 12, 3, + 3, 4, 21, 7, 13, 14, 15, 16, 17, 28, + 3, 3, 21, 21, 7, 27, 25, 26, 3, 28, + 33, 3, 36, 13, 14, 15, 16, 17, 8, 9, + 10, 11, 12, 22, 23, 24, 34, 35, 28, 18, + 19, 20, 33, 27, 3, 33, 3, 3, 34, 3, + 3, 57, 35, 60, 35, 77, 34, 44, 35, 58, + 86, 37, 87, -1, -1, -1, 41 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 36, 0, 13, 14, 15, 16, 17, 22, 23, - 25, 37, 38, 39, 41, 43, 50, 51, 3, 4, - 3, 18, 53, 3, 7, 40, 19, 20, 21, 54, - 42, 40, 24, 49, 3, 3, 30, 44, 52, 45, - 24, 57, 41, 46, 47, 48, 3, 55, 56, 30, - 58, 40, 31, 32, 32, 59, 44, 48, 56, 3, - 40, 60, 61, 62, 8, 9, 10, 11, 12, 33, - 63, 31, 32, 3, 3, 5, 6, 58, 64, 65, - 62, 34, 63, 65 + 0, 39, 0, 13, 14, 15, 16, 17, 25, 26, + 28, 40, 41, 42, 44, 46, 53, 54, 3, 4, + 3, 21, 56, 3, 7, 43, 22, 23, 24, 57, + 45, 43, 27, 52, 3, 3, 33, 47, 55, 48, + 27, 60, 18, 19, 20, 49, 50, 51, 3, 58, + 59, 33, 61, 3, 3, 44, 34, 35, 35, 62, + 3, 51, 59, 3, 43, 63, 64, 65, 47, 8, + 9, 10, 11, 12, 36, 66, 34, 35, 3, 3, + 5, 6, 61, 67, 68, 65, 37, 66, 68 }; #define yyerrok (yyerrstatus = 0) @@ -1622,7 +1628,7 @@ yyreduce: case 8: /* Line 1806 of yacc.c */ -#line 124 "config_parser.yy" +#line 127 "config_parser.yy" { context->HandleInclude((yyvsp[(2) - (2)].text), false, yylloc); } @@ -1631,7 +1637,7 @@ yyreduce: case 9: /* Line 1806 of yacc.c */ -#line 128 "config_parser.yy" +#line 131 "config_parser.yy" { context->HandleInclude((yyvsp[(2) - (2)].text), true, yylloc); } @@ -1640,7 +1646,7 @@ yyreduce: case 10: /* Line 1806 of yacc.c */ -#line 133 "config_parser.yy" +#line 136 "config_parser.yy" { context->HandleLibrary((yyvsp[(2) - (2)].text)); } @@ -1649,7 +1655,7 @@ yyreduce: case 12: /* Line 1806 of yacc.c */ -#line 139 "config_parser.yy" +#line 142 "config_parser.yy" { (yyval.text) = (yyvsp[(1) - (1)].text); } @@ -1658,7 +1664,7 @@ yyreduce: case 13: /* Line 1806 of yacc.c */ -#line 145 "config_parser.yy" +#line 148 "config_parser.yy" { String name = String((yyvsp[(3) - (3)].text)); m_Type = ConfigCompilerContext::GetContext()->GetType(name); @@ -1676,10 +1682,16 @@ yyreduce: case 14: /* Line 1806 of yacc.c */ -#line 158 "config_parser.yy" +#line 161 "config_parser.yy" { TypeRuleList::Ptr ruleList = *(yyvsp[(6) - (6)].variant); m_Type->GetRuleList()->AddRules(ruleList); + m_Type->GetRuleList()->AddRequires(ruleList); + + String validator = ruleList->GetValidator(); + if (!validator.IsEmpty()) + m_Type->GetRuleList()->SetValidator(validator); + delete (yyvsp[(6) - (6)].variant); } break; @@ -1687,7 +1699,7 @@ yyreduce: case 15: /* Line 1806 of yacc.c */ -#line 166 "config_parser.yy" +#line 175 "config_parser.yy" { (yyval.num) = 0; } @@ -1696,7 +1708,7 @@ yyreduce: case 16: /* Line 1806 of yacc.c */ -#line 170 "config_parser.yy" +#line 179 "config_parser.yy" { (yyval.num) = 1; } @@ -1705,7 +1717,7 @@ yyreduce: case 17: /* Line 1806 of yacc.c */ -#line 176 "config_parser.yy" +#line 185 "config_parser.yy" { m_RuleLists.push(boost::make_shared()); } @@ -1714,7 +1726,7 @@ yyreduce: case 18: /* Line 1806 of yacc.c */ -#line 181 "config_parser.yy" +#line 190 "config_parser.yy" { (yyval.variant) = new Value(m_RuleLists.top()); m_RuleLists.pop(); @@ -1724,20 +1736,27 @@ yyreduce: case 24: /* Line 1806 of yacc.c */ -#line 196 "config_parser.yy" +#line 205 "config_parser.yy" { - TypeRule rule((yyvsp[(1) - (2)].type), (yyvsp[(2) - (2)].text), TypeRuleList::Ptr(), yylloc); - m_RuleLists.top()->AddRule(rule); + m_RuleLists.top()->AddRequire((yyvsp[(2) - (2)].text)); } break; case 25: /* Line 1806 of yacc.c */ -#line 201 "config_parser.yy" +#line 209 "config_parser.yy" { - TypeRule rule((yyvsp[(1) - (3)].type), (yyvsp[(2) - (3)].text), *(yyvsp[(3) - (3)].variant), yylloc); - delete (yyvsp[(3) - (3)].variant); + m_RuleLists.top()->SetValidator((yyvsp[(2) - (2)].text)); + } + break; + + case 26: + +/* Line 1806 of yacc.c */ +#line 213 "config_parser.yy" + { + TypeRule rule((yyvsp[(2) - (3)].type), (yyvsp[(3) - (3)].text), TypeRuleList::Ptr(), yylloc); m_RuleLists.top()->AddRule(rule); } break; @@ -1745,35 +1764,46 @@ yyreduce: case 27: /* Line 1806 of yacc.c */ -#line 210 "config_parser.yy" +#line 218 "config_parser.yy" + { + TypeRule rule((yyvsp[(2) - (4)].type), (yyvsp[(3) - (4)].text), *(yyvsp[(4) - (4)].variant), yylloc); + delete (yyvsp[(4) - (4)].variant); + m_RuleLists.top()->AddRule(rule); + } + break; + + case 29: + +/* Line 1806 of yacc.c */ +#line 227 "config_parser.yy" { m_Type->SetParent((yyvsp[(2) - (2)].text)); } break; - case 32: - -/* Line 1806 of yacc.c */ -#line 220 "config_parser.yy" - { - (yyval.type) = (yyvsp[(1) - (1)].type); - } - break; - - case 33: - -/* Line 1806 of yacc.c */ -#line 226 "config_parser.yy" - { - m_Abstract = false; - m_Local = false; - } - break; - case 34: /* Line 1806 of yacc.c */ -#line 231 "config_parser.yy" +#line 237 "config_parser.yy" + { + (yyval.type) = (yyvsp[(1) - (1)].type); + } + break; + + case 35: + +/* Line 1806 of yacc.c */ +#line 243 "config_parser.yy" + { + m_Abstract = false; + m_Local = false; + } + break; + + case 36: + +/* Line 1806 of yacc.c */ +#line 248 "config_parser.yy" { m_Item = boost::make_shared(yylloc); m_Item->SetType((yyvsp[(4) - (5)].text)); @@ -1781,10 +1811,10 @@ yyreduce: } break; - case 35: + case 37: /* Line 1806 of yacc.c */ -#line 237 "config_parser.yy" +#line 254 "config_parser.yy" { ExpressionList::Ptr exprl = *(yyvsp[(8) - (8)].variant); delete (yyvsp[(8) - (8)].variant); @@ -1798,57 +1828,57 @@ yyreduce: } break; - case 38: + case 40: /* Line 1806 of yacc.c */ -#line 255 "config_parser.yy" +#line 272 "config_parser.yy" { m_Abstract = true; } break; - case 39: + case 41: /* Line 1806 of yacc.c */ -#line 259 "config_parser.yy" +#line 276 "config_parser.yy" { m_Local = true; } break; - case 42: + case 44: /* Line 1806 of yacc.c */ -#line 269 "config_parser.yy" +#line 286 "config_parser.yy" { m_Item->AddParent((yyvsp[(1) - (1)].text)); free((yyvsp[(1) - (1)].text)); } break; - case 45: + case 47: /* Line 1806 of yacc.c */ -#line 280 "config_parser.yy" +#line 297 "config_parser.yy" { m_ExpressionLists.push(boost::make_shared()); } break; - case 46: + case 48: /* Line 1806 of yacc.c */ -#line 285 "config_parser.yy" +#line 302 "config_parser.yy" { (yyval.variant) = new Value(m_ExpressionLists.top()); m_ExpressionLists.pop(); } break; - case 52: + case 54: /* Line 1806 of yacc.c */ -#line 300 "config_parser.yy" +#line 317 "config_parser.yy" { Expression expr((yyvsp[(1) - (3)].text), (yyvsp[(2) - (3)].op), *(yyvsp[(3) - (3)].variant), yylloc); free((yyvsp[(1) - (3)].text)); @@ -1858,10 +1888,10 @@ yyreduce: } break; - case 53: + case 55: /* Line 1806 of yacc.c */ -#line 308 "config_parser.yy" +#line 325 "config_parser.yy" { Expression subexpr((yyvsp[(3) - (6)].text), (yyvsp[(5) - (6)].op), *(yyvsp[(6) - (6)].variant), yylloc); free((yyvsp[(3) - (6)].text)); @@ -1877,10 +1907,10 @@ yyreduce: } break; - case 54: + case 56: /* Line 1806 of yacc.c */ -#line 322 "config_parser.yy" +#line 339 "config_parser.yy" { Expression expr((yyvsp[(1) - (1)].text), OperatorSet, (yyvsp[(1) - (1)].text), yylloc); free((yyvsp[(1) - (1)].text)); @@ -1889,47 +1919,47 @@ yyreduce: } break; - case 59: - -/* Line 1806 of yacc.c */ -#line 335 "config_parser.yy" - { - (yyval.op) = (yyvsp[(1) - (1)].op); - } - break; - - case 60: - -/* Line 1806 of yacc.c */ -#line 341 "config_parser.yy" - { - (yyval.variant) = new Value((yyvsp[(1) - (1)].text)); - free((yyvsp[(1) - (1)].text)); - } - break; - case 61: /* Line 1806 of yacc.c */ -#line 346 "config_parser.yy" +#line 352 "config_parser.yy" { - (yyval.variant) = new Value((yyvsp[(1) - (1)].num)); + (yyval.op) = (yyvsp[(1) - (1)].op); } break; case 62: /* Line 1806 of yacc.c */ -#line 350 "config_parser.yy" +#line 358 "config_parser.yy" { - (yyval.variant) = new Value(); + (yyval.variant) = new Value((yyvsp[(1) - (1)].text)); + free((yyvsp[(1) - (1)].text)); + } + break; + + case 63: + +/* Line 1806 of yacc.c */ +#line 363 "config_parser.yy" + { + (yyval.variant) = new Value((yyvsp[(1) - (1)].num)); } break; case 64: /* Line 1806 of yacc.c */ -#line 357 "config_parser.yy" +#line 367 "config_parser.yy" + { + (yyval.variant) = new Value(); + } + break; + + case 66: + +/* Line 1806 of yacc.c */ +#line 374 "config_parser.yy" { (yyval.variant) = (yyvsp[(1) - (1)].variant); } @@ -1938,7 +1968,7 @@ yyreduce: /* Line 1806 of yacc.c */ -#line 1942 "config_parser.cc" +#line 1972 "config_parser.cc" default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -2176,6 +2206,6 @@ yyreturn: /* Line 2067 of yacc.c */ -#line 361 "config_parser.yy" +#line 378 "config_parser.yy" diff --git a/lib/config/config_parser.h b/lib/config/config_parser.h index 63c7dabbe..975524e85 100644 --- a/lib/config/config_parser.h +++ b/lib/config/config_parser.h @@ -87,14 +87,17 @@ using namespace icinga; T_TYPE_STRING = 270, T_TYPE_SCALAR = 271, T_TYPE_ANY = 272, - T_TYPE = 273, - T_ABSTRACT = 274, - T_LOCAL = 275, - T_OBJECT = 276, - T_INCLUDE = 277, - T_LIBRARY = 278, - T_INHERITS = 279, - T_PARTIAL = 280 + T_VALIDATOR = 273, + T_REQUIRE = 274, + T_ATTRIBUTE = 275, + T_TYPE = 276, + T_ABSTRACT = 277, + T_LOCAL = 278, + T_OBJECT = 279, + T_INCLUDE = 280, + T_LIBRARY = 281, + T_INHERITS = 282, + T_PARTIAL = 283 }; #endif /* Tokens. */ @@ -113,14 +116,17 @@ using namespace icinga; #define T_TYPE_STRING 270 #define T_TYPE_SCALAR 271 #define T_TYPE_ANY 272 -#define T_TYPE 273 -#define T_ABSTRACT 274 -#define T_LOCAL 275 -#define T_OBJECT 276 -#define T_INCLUDE 277 -#define T_LIBRARY 278 -#define T_INHERITS 279 -#define T_PARTIAL 280 +#define T_VALIDATOR 273 +#define T_REQUIRE 274 +#define T_ATTRIBUTE 275 +#define T_TYPE 276 +#define T_ABSTRACT 277 +#define T_LOCAL 278 +#define T_OBJECT 279 +#define T_INCLUDE 280 +#define T_LIBRARY 281 +#define T_INHERITS 282 +#define T_PARTIAL 283 @@ -141,7 +147,7 @@ typedef union YYSTYPE /* Line 2068 of yacc.c */ -#line 145 "config_parser.h" +#line 151 "config_parser.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ diff --git a/lib/config/config_parser.yy b/lib/config/config_parser.yy index b19d99a28..8bb83388f 100644 --- a/lib/config/config_parser.yy +++ b/lib/config/config_parser.yy @@ -58,6 +58,9 @@ using namespace icinga; %token T_TYPE_STRING %token T_TYPE_SCALAR %token T_TYPE_ANY +%token T_VALIDATOR +%token T_REQUIRE +%token T_ATTRIBUTE %token T_TYPE %token T_ABSTRACT %token T_LOCAL @@ -158,6 +161,12 @@ type: partial_specifier T_TYPE identifier { TypeRuleList::Ptr ruleList = *$6; m_Type->GetRuleList()->AddRules(ruleList); + m_Type->GetRuleList()->AddRequires(ruleList); + + String validator = ruleList->GetValidator(); + if (!validator.IsEmpty()) + m_Type->GetRuleList()->SetValidator(validator); + delete $6; } ; @@ -192,15 +201,23 @@ typerules_inner: /* empty */ | typerules_inner ',' typerule ; -typerule: type identifier +typerule: T_REQUIRE T_STRING { - TypeRule rule($1, $2, TypeRuleList::Ptr(), yylloc); + m_RuleLists.top()->AddRequire($2); + } + | T_VALIDATOR T_STRING + { + m_RuleLists.top()->SetValidator($2); + } + | T_ATTRIBUTE type T_STRING + { + TypeRule rule($2, $3, TypeRuleList::Ptr(), yylloc); m_RuleLists.top()->AddRule(rule); } - | type identifier typerulelist + | T_ATTRIBUTE type T_STRING typerulelist { - TypeRule rule($1, $2, *$3, yylloc); - delete $3; + TypeRule rule($2, $3, *$4, yylloc); + delete $4; m_RuleLists.top()->AddRule(rule); } ; diff --git a/lib/config/configcompilercontext.cpp b/lib/config/configcompilercontext.cpp index f973426a5..a6fdf29dc 100644 --- a/lib/config/configcompilercontext.cpp +++ b/lib/config/configcompilercontext.cpp @@ -26,7 +26,7 @@ using namespace icinga; ConfigCompilerContext *ConfigCompilerContext::m_Context = NULL; ConfigCompilerContext::ConfigCompilerContext(void) - : m_Flags(0) + : m_Unit(Utility::NewUUID()), m_Flags(0) { } void ConfigCompilerContext::AddItem(const ConfigItem::Ptr& item) @@ -101,6 +101,11 @@ ConfigCompilerContext *ConfigCompilerContext::GetContext(void) return m_Context; } +String ConfigCompilerContext::GetUnit(void) const +{ + return m_Unit; +} + void ConfigCompilerContext::Validate(void) { SetContext(this); @@ -108,8 +113,11 @@ void ConfigCompilerContext::Validate(void) BOOST_FOREACH(const ConfigItem::Ptr& item, m_Items) { ConfigType::Ptr ctype = GetType(item->GetType()); - if (!ctype) + if (!ctype) { + AddError(true, "No validation type found for object '" + item->GetName() + "' of type '" + item->GetType() + "'"); + continue; + } ctype->ValidateItem(item); } @@ -121,8 +129,9 @@ void ConfigCompilerContext::ActivateItems(void) { assert(m_Context == NULL); - Logger::Write(LogInformation, "config", "Executing config items..."); + Logger::Write(LogInformation, "config", "Activating config items in compilation unit '" + m_Unit + "'"); BOOST_FOREACH(const ConfigItem::Ptr& item, m_Items) { item->Commit(); } } + diff --git a/lib/config/configcompilercontext.h b/lib/config/configcompilercontext.h index 97a8d9e32..e4b79bf0d 100644 --- a/lib/config/configcompilercontext.h +++ b/lib/config/configcompilercontext.h @@ -63,6 +63,8 @@ public: void SetFlags(int flags); int GetFlags(void) const; + String GetUnit(void) const; + void Validate(void); void ActivateItems(void); @@ -70,6 +72,8 @@ public: static ConfigCompilerContext *GetContext(void); private: + String m_Unit; + int m_Flags; vector > m_Items; diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 77628afd0..f37261b2d 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -35,9 +35,9 @@ boost::signal ConfigItem::OnRemoved; * @param debuginfo Debug information. */ ConfigItem::ConfigItem(const String& type, const String& name, - const ExpressionList::Ptr& exprl, const vector& parents, - const DebugInfo& debuginfo) - : m_Type(type), m_Name(name), m_ExpressionList(exprl), + const String& unit, const ExpressionList::Ptr& exprl, + const vector& parents, const DebugInfo& debuginfo) + : m_Type(type), m_Name(name), m_Unit(unit), m_ExpressionList(exprl), m_Parents(parents), m_DebugInfo(debuginfo) { } @@ -62,6 +62,16 @@ String ConfigItem::GetName(void) const return m_Name; } +/** + * Retrieves the name of the compilation unit this item belongs to. + * + * @returns The unit name. + */ +String ConfigItem::GetUnit(void) const +{ + return m_Unit; +} + /** * Retrieves the debug information for the configuration item. * @@ -308,6 +318,12 @@ ConfigItem::Ptr ConfigItem::GetObject(const String& type, const String& name) return ConfigItem::Ptr(); } +/** + * Dumps the config item to the specified stream using Icinga's config item + * syntax. + * + * @param fp The stream. + */ void ConfigItem::Dump(ostream& fp) const { fp << "object \"" << m_Type << "\" \"" << m_Name << "\""; @@ -330,3 +346,22 @@ void ConfigItem::Dump(ostream& fp) const m_ExpressionList->Dump(fp, 1); fp << "}" << "\n"; } + +void ConfigItem::UnloadUnit(const String& unit) +{ + Logger::Write(LogInformation, "config", "Unloading config items from compilation unit '" + unit + "'"); + + vector obsoleteItems; + + ConfigItem::Ptr item; + BOOST_FOREACH(tie(tuples::ignore, item), m_Items) { + if (item->GetUnit() != unit) + continue; + + obsoleteItems.push_back(item); + } + + BOOST_FOREACH(item, obsoleteItems) { + item->Unregister(); + } +} diff --git a/lib/config/configitem.h b/lib/config/configitem.h index 1bc3d8892..14ea0965c 100644 --- a/lib/config/configitem.h +++ b/lib/config/configitem.h @@ -34,12 +34,13 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - ConfigItem(const String& type, const String& name, + ConfigItem(const String& type, const String& name, const String& unit, const ExpressionList::Ptr& exprl, const vector& parents, const DebugInfo& debuginfo); String GetType(void) const; String GetName(void) const; + String GetUnit(void) const; vector GetParents(void) const; @@ -59,6 +60,8 @@ public: static ConfigItem::Ptr GetObject(const String& type, const String& name); + static void UnloadUnit(const String& unit); + static boost::signal OnCommitted; static boost::signal OnRemoved; @@ -73,6 +76,7 @@ private: String m_Type; /**< The object type. */ String m_Name; /**< The name. */ + String m_Unit; /**< The compilation unit. */ ExpressionList::Ptr m_ExpressionList; vector m_Parents; /**< The names of parent configuration diff --git a/lib/config/configitembuilder.cpp b/lib/config/configitembuilder.cpp index ce27dc782..3111a23bf 100644 --- a/lib/config/configitembuilder.cpp +++ b/lib/config/configitembuilder.cpp @@ -48,6 +48,11 @@ void ConfigItemBuilder::SetName(const String& name) m_Name = name; } +void ConfigItemBuilder::SetUnit(const String& unit) +{ + m_Unit = unit; +} + void ConfigItemBuilder::SetLocal(bool local) { m_Local = local; @@ -88,6 +93,12 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void) throw_exception(invalid_argument(msgbuf.str())); } + if (!DynamicType::GetByName(m_Type)) { + stringstream msgbuf; + msgbuf << "The type '" + m_Type + "' is unknown: " << m_DebugInfo; + throw_exception(invalid_argument(msgbuf.str())); + } + if (m_Name.IsEmpty()) { stringstream msgbuf; msgbuf << "The name of an object may not be empty: " << m_DebugInfo; @@ -111,6 +122,6 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void) Expression abstractExpr("__abstract", OperatorSet, m_Abstract, m_DebugInfo); exprl->AddExpression(abstractExpr); - return boost::make_shared(m_Type, m_Name, exprl, m_Parents, + return boost::make_shared(m_Type, m_Name, m_Unit, exprl, m_Parents, m_DebugInfo); } diff --git a/lib/config/configitembuilder.h b/lib/config/configitembuilder.h index a857c3f11..08057baef 100644 --- a/lib/config/configitembuilder.h +++ b/lib/config/configitembuilder.h @@ -40,6 +40,7 @@ public: void SetType(const String& type); void SetName(const String& name); + void SetUnit(const String& unit); void SetLocal(bool local); void SetAbstract(bool abstract); @@ -55,6 +56,7 @@ public: private: String m_Type; /**< The object type. */ String m_Name; /**< The name. */ + String m_Unit; /**< The compilation unit. */ bool m_Local; /**< Whether the item is local. */ bool m_Abstract; /**< Whether the item is abstract. */ vector m_Parents; /**< The names of parent configuration diff --git a/lib/config/configtype.cpp b/lib/config/configtype.cpp index 90b5eebfb..22c3725de 100644 --- a/lib/config/configtype.cpp +++ b/lib/config/configtype.cpp @@ -50,12 +50,16 @@ DebugInfo ConfigType::GetDebugInfo(void) const return m_DebugInfo; } -void ConfigType::ValidateItem(const ConfigItem::Ptr& object) const +void ConfigType::ValidateItem(const ConfigItem::Ptr& item) const { - Dictionary::Ptr attrs = object->Link(); + Dictionary::Ptr attrs = item->Link(); + + /* Don't validate abstract items. */ + if (attrs->Get("__abstract")) + return; vector locations; - locations.push_back("Object '" + object->GetName() + "' (Type: '" + object->GetType() + "')"); + locations.push_back("Object '" + item->GetName() + "' (Type: '" + item->GetType() + "')"); ConfigType::Ptr parent; if (m_Parent.IsEmpty()) { @@ -74,9 +78,38 @@ void ConfigType::ValidateItem(const ConfigItem::Ptr& object) const ValidateDictionary(attrs, ruleLists, locations); } +String ConfigType::LocationToString(const vector& locations) +{ + bool first = true; + String stack; + BOOST_FOREACH(const String& location, locations) { + if (!first) + stack += " -> "; + else + first = false; + + stack += location; + } + + return stack; +} + void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary, const vector& ruleLists, vector& locations) { + BOOST_FOREACH(const TypeRuleList::Ptr& ruleList, ruleLists) { + BOOST_FOREACH(const String& require, ruleList->GetRequires()) { + locations.push_back("Attribute '" + require + "'"); + + Value value = dictionary->Get(require); + + if (value.IsEmpty()) + ConfigCompilerContext::GetContext()->AddError(false, "Required attribute is missing: " + LocationToString(locations)); + + locations.pop_back(); + } + } + String key; Value value; BOOST_FOREACH(tie(key, value), dictionary) { @@ -87,7 +120,7 @@ void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary, BOOST_FOREACH(const TypeRuleList::Ptr& ruleList, ruleLists) { TypeRuleList::Ptr subRuleList; - TypeValidationResult result = ruleList->Validate(key, value, &subRuleList); + TypeValidationResult result = ruleList->ValidateAttribute(key, value, &subRuleList); if (subRuleList) subRuleLists.push_back(subRuleList); @@ -101,21 +134,10 @@ void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary, overallResult = result; } - bool first = true; - String stack; - BOOST_FOREACH(const String& location, locations) { - if (!first) - stack += " -> "; - else - first = false; - - stack += location; - } - if (overallResult == ValidationUnknownField) - ConfigCompilerContext::GetContext()->AddError(true, "Unknown attribute: " + stack); + ConfigCompilerContext::GetContext()->AddError(true, "Unknown attribute: " + LocationToString(locations)); else if (overallResult == ValidationInvalidType) - ConfigCompilerContext::GetContext()->AddError(false, "Invalid type for attribute: " + stack); + ConfigCompilerContext::GetContext()->AddError(false, "Invalid type for attribute: " + LocationToString(locations)); if (subRuleLists.size() > 0 && value.IsObjectType()) ValidateDictionary(value, subRuleLists, locations); diff --git a/lib/config/configtype.h b/lib/config/configtype.h index c028092bc..4251a5f3d 100644 --- a/lib/config/configtype.h +++ b/lib/config/configtype.h @@ -56,6 +56,7 @@ private: static void ValidateDictionary(const Dictionary::Ptr& dictionary, const vector& ruleLists, vector& locations); + static String LocationToString(const vector& locations); }; } diff --git a/lib/config/typerulelist.cpp b/lib/config/typerulelist.cpp index 7df540d9e..f1ab7860b 100644 --- a/lib/config/typerulelist.cpp +++ b/lib/config/typerulelist.cpp @@ -21,6 +21,58 @@ using namespace icinga; +/** + * Sets the validator method for a rule list. + * + * @param validator The validator. + */ +void TypeRuleList::SetValidator(const String& validator) +{ + m_Validator = validator; +} + +/** + * Retrieves the validator method. + * + * @returns The validator method. + */ +String TypeRuleList::GetValidator(void) const +{ + return m_Validator; +} + +/** + * Adds an attribute to the list of required attributes. + * + * @param attr The new required attribute. + */ +void TypeRuleList::AddRequire(const String& attr) +{ + m_Requires.push_back(attr); +} + +/** + * Retrieves the list of required attributes. + * + * @returns The list of required attributes. + */ +vector TypeRuleList::GetRequires(void) const +{ + return m_Requires; +} + +/** + * Adds all requires from the specified rule list. + * + * @param ruleList The rule list to copy requires from. + */ +void TypeRuleList::AddRequires(const TypeRuleList::Ptr& ruleList) +{ + BOOST_FOREACH(const String& require, ruleList->m_Requires) { + AddRequire(require); + } +} + /** * Adds a rule to a rule list. * @@ -61,7 +113,8 @@ size_t TypeRuleList::GetLength(void) const * @param[out] subRules The list of sub-rules for the matching rule. * @returns The validation result. */ -TypeValidationResult TypeRuleList::Validate(const String& name, const Value& value, TypeRuleList::Ptr *subRules) const +TypeValidationResult TypeRuleList::ValidateAttribute(const String& name, + const Value& value, TypeRuleList::Ptr *subRules) const { bool foundField = false; BOOST_FOREACH(const TypeRule& rule, m_Rules) { diff --git a/lib/config/typerulelist.h b/lib/config/typerulelist.h index b12d3af1a..6c26213f2 100644 --- a/lib/config/typerulelist.h +++ b/lib/config/typerulelist.h @@ -46,14 +46,23 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; + void SetValidator(const String& validator); + String GetValidator(void) const; + + void AddRequire(const String& attr); + void AddRequires(const TypeRuleList::Ptr& ruleList); + vector GetRequires(void) const; + void AddRule(const TypeRule& rule); void AddRules(const TypeRuleList::Ptr& ruleList); - TypeValidationResult Validate(const String& name, const Value& value, TypeRuleList::Ptr *subRules) const; + TypeValidationResult ValidateAttribute(const String& name, const Value& value, TypeRuleList::Ptr *subRules) const; size_t GetLength(void) const; private: + String m_Validator; + vector m_Requires; vector m_Rules; }; diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index 6a4977721..a1063988a 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -24,6 +24,8 @@ using namespace icinga; map > Host::m_ServicesCache; bool Host::m_ServicesCacheValid = true; +REGISTER_SCRIPTFUNCTION("native::ValidateHostItem", &Host::ValidateHostItem); + static AttributeDescription hostAttributes[] = { { "acknowledgement", Attribute_Replicated }, { "acknowledgement_expiry", Attribute_Replicated }, @@ -405,3 +407,18 @@ void Host::ValidateServicesCache(void) m_ServicesCacheValid = true; } +void Host::ValidateHostItem(const ScriptTask::Ptr& task, const vector& arguments) +{ + if (arguments.size() < 1) + throw_exception(invalid_argument("Missing argument: Host config item must be specified.")); + + if (arguments.size() < 2) + throw_exception(invalid_argument("Missing argument: Attribute dictionary must be specified.")); + + ConfigItem::Ptr item = arguments[0]; + Dictionary::Ptr attrs = arguments[1]; + + // TODO: validate item + + ConfigCompilerContext::GetContext()->AddError(false, "Hello World!"); +} diff --git a/lib/icinga/host.h b/lib/icinga/host.h index d3d07175a..3ee32cd43 100644 --- a/lib/icinga/host.h +++ b/lib/icinga/host.h @@ -63,6 +63,9 @@ public: set > GetServices(void) const; static void InvalidateServicesCache(void); + static void ValidateHostItem(const ScriptTask::Ptr& task, + const std::vector& arguments); + protected: void OnAttributeChanged(const String& name, const Value& oldValue);