mirror of https://github.com/Icinga/icinga2.git
parent
312756a886
commit
7a150d2c29
|
@ -38,28 +38,35 @@ static bool g_ReloadConfig = false;
|
|||
static Timer::Ptr g_ReloadConfigTimer;
|
||||
#endif /* _WIN32 */
|
||||
|
||||
static bool LoadConfigFiles(void)
|
||||
static bool LoadConfigFiles(bool validateOnly)
|
||||
{
|
||||
set<ConfigItem::Ptr> allItems;
|
||||
ConfigCompilerContext context;
|
||||
|
||||
try {
|
||||
BOOST_FOREACH(const String& configPath, g_AppParams["config"].as<vector<String> >()) {
|
||||
vector<ConfigItem::Ptr> items;
|
||||
vector<ConfigType::Ptr> types;
|
||||
ConfigCompilerContext::SetContext(&context);
|
||||
|
||||
ConfigCompiler::CompileFile(configPath, &items, &types);
|
||||
BOOST_FOREACH(const String& configPath, g_AppParams["config"].as<vector<String> >()) {
|
||||
ConfigCompiler::CompileFile(configPath);
|
||||
}
|
||||
|
||||
Logger::Write(LogInformation, "icinga-app", "Registering config types...");
|
||||
BOOST_FOREACH(const ConfigType::Ptr& type, types) {
|
||||
type->Commit();
|
||||
}
|
||||
ConfigCompilerContext::SetContext(NULL);
|
||||
|
||||
Logger::Write(LogInformation, "icinga-app", "Executing config items...");
|
||||
BOOST_FOREACH(const ConfigItem::Ptr& item, items) {
|
||||
item->Commit();
|
||||
}
|
||||
context.Validate();
|
||||
|
||||
Logger::Write(LogInformation, "icinga-app", "Validating config items...");
|
||||
bool hasError = false;
|
||||
|
||||
BOOST_FOREACH(const ConfigCompilerError& error, context.GetErrors()) {
|
||||
if (error.Warning) {
|
||||
Logger::Write(LogWarning, "icinga-app", "Config warning: " + error.Message);
|
||||
} else {
|
||||
hasError = true;
|
||||
Logger::Write(LogCritical, "icinga-app", "Config error: " + error.Message);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasError)
|
||||
return false;
|
||||
|
||||
/* Logger::Write(LogInformation, "icinga-app", "Validating config items...");
|
||||
DynamicType::Ptr type;
|
||||
BOOST_FOREACH(tie(tuples::ignore, type), DynamicType::GetTypes()) {
|
||||
ConfigType::Ptr ctype = ConfigType::GetByName(type->GetName());
|
||||
|
@ -74,32 +81,26 @@ static bool LoadConfigFiles(void)
|
|||
BOOST_FOREACH(tie(tuples::ignore, object), type->GetObjects()) {
|
||||
ctype->ValidateObject(object);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
std::copy(items.begin(), items.end(), std::inserter(allItems, allItems.begin()));
|
||||
}
|
||||
context.ActivateItems();
|
||||
|
||||
BOOST_FOREACH(const ConfigItem::WeakPtr& witem, g_ConfigItems) {
|
||||
ConfigItem::Ptr item = witem.lock();
|
||||
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;
|
||||
/* Ignore this item if it's not active anymore */
|
||||
if (!item || ConfigItem::GetObject(item->GetType(), item->GetName()) != item)
|
||||
continue;
|
||||
|
||||
/* Remove the object if it's not in the list of current items */
|
||||
if (allItems.find(item) == allItems.end())
|
||||
item->Unregister();
|
||||
}
|
||||
|
||||
g_ConfigItems.clear();
|
||||
std::copy(allItems.begin(), allItems.end(), std::back_inserter(g_ConfigItems));
|
||||
|
||||
return true;
|
||||
} catch (const exception& ex) {
|
||||
Logger::Write(LogCritical, "icinga-app", "Configuration error: " + String(ex.what()));
|
||||
return false;
|
||||
item->Unregister();
|
||||
}
|
||||
|
||||
g_ConfigItems.clear();
|
||||
|
||||
vector<ConfigItem::Ptr> items = context.GetItems();
|
||||
std::copy(items.begin(), items.end(), std::back_inserter(g_ConfigItems));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -107,7 +108,7 @@ static void ReloadConfigTimerHandler(void)
|
|||
{
|
||||
if (g_ReloadConfig) {
|
||||
Logger::Write(LogInformation, "icinga-app", "Received SIGHUP. Reloading config files.");
|
||||
LoadConfigFiles();
|
||||
LoadConfigFiles(false);
|
||||
g_ReloadConfig = false;
|
||||
}
|
||||
}
|
||||
|
@ -241,21 +242,23 @@ int main(int argc, char **argv)
|
|||
|
||||
DynamicObject::BeginTx();
|
||||
|
||||
if (!LoadConfigFiles())
|
||||
bool validateOnly = g_AppParams.count("validate");
|
||||
|
||||
if (!LoadConfigFiles(validateOnly))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
DynamicObject::FinishTx();
|
||||
|
||||
if (validateOnly) {
|
||||
Logger::Write(LogInformation, "icinga-app", "Terminating as requested by --validate.");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
Application::Ptr app = Application::GetInstance();
|
||||
|
||||
if (!app)
|
||||
throw_exception(runtime_error("Configuration must create an Application object."));
|
||||
|
||||
if (g_AppParams.count("validate")) {
|
||||
Logger::Write(LogInformation, "icinga-app", "Terminating as requested by --validate.");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (g_AppParams.count("daemonize")) {
|
||||
Logger::Write(LogInformation, "icinga", "Daemonizing.");
|
||||
Utility::Daemonize();
|
||||
|
|
|
@ -88,7 +88,7 @@ String Value::Serialize(void) const
|
|||
|
||||
char *jsonString;
|
||||
|
||||
if (Application::GetInstance()->IsDebugging())
|
||||
if (Application::IsDebugging())
|
||||
jsonString = cJSON_Print(json);
|
||||
else
|
||||
jsonString = cJSON_PrintUnformatted(json);
|
||||
|
|
|
@ -11,6 +11,8 @@ AM_YFLAGS = -d
|
|||
libconfig_la_SOURCES = \
|
||||
configcompiler.cpp \
|
||||
configcompiler.h \
|
||||
configcompilercontext.cpp \
|
||||
configcompilercontext.h \
|
||||
config_lexer.ll \
|
||||
config_parser.yy \
|
||||
i2-config.h \
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="configcompiler.h" />
|
||||
<ClInclude Include="configcompilercontext.h" />
|
||||
<ClInclude Include="configitem.h" />
|
||||
<ClInclude Include="configitembuilder.h" />
|
||||
<ClInclude Include="configtype.h" />
|
||||
|
@ -33,6 +34,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="configcompiler.cpp" />
|
||||
<ClCompile Include="configcompilercontext.cpp" />
|
||||
<ClCompile Include="configitem.cpp" />
|
||||
<ClCompile Include="configitembuilder.cpp" />
|
||||
<ClCompile Include="configtype.cpp" />
|
||||
|
|
|
@ -246,7 +246,13 @@ static ConfigType::Ptr m_Type;
|
|||
|
||||
void ConfigCompiler::Compile(void)
|
||||
{
|
||||
yyparse(this);
|
||||
assert(ConfigCompilerContext::GetContext() != NULL);
|
||||
|
||||
try {
|
||||
yyparse(this);
|
||||
} catch (const exception& ex) {
|
||||
ConfigCompilerContext::GetContext()->AddError(false, ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
#define scanner (context->GetScanner())
|
||||
|
@ -254,7 +260,7 @@ void ConfigCompiler::Compile(void)
|
|||
|
||||
|
||||
/* Line 343 of yacc.c */
|
||||
#line 258 "config_parser.cc"
|
||||
#line 264 "config_parser.cc"
|
||||
|
||||
#ifdef short
|
||||
# undef short
|
||||
|
@ -565,13 +571,13 @@ static const yytype_int8 yyrhs[] =
|
|||
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
|
||||
static const yytype_uint16 yyrline[] =
|
||||
{
|
||||
0, 110, 110, 111, 114, 114, 114, 114, 117, 121,
|
||||
126, 131, 132, 139, 138, 160, 163, 170, 169, 181,
|
||||
182, 184, 185, 186, 189, 194, 202, 203, 209, 210,
|
||||
211, 212, 213, 220, 225, 220, 244, 245, 248, 252,
|
||||
258, 259, 262, 269, 270, 274, 273, 285, 286, 288,
|
||||
289, 290, 293, 301, 315, 324, 325, 326, 327, 328,
|
||||
334, 339, 343, 349, 350
|
||||
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
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -1616,7 +1622,7 @@ yyreduce:
|
|||
case 8:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 118 "config_parser.yy"
|
||||
#line 124 "config_parser.yy"
|
||||
{
|
||||
context->HandleInclude((yyvsp[(2) - (2)].text), false, yylloc);
|
||||
}
|
||||
|
@ -1625,7 +1631,7 @@ yyreduce:
|
|||
case 9:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 122 "config_parser.yy"
|
||||
#line 128 "config_parser.yy"
|
||||
{
|
||||
context->HandleInclude((yyvsp[(2) - (2)].text), true, yylloc);
|
||||
}
|
||||
|
@ -1634,7 +1640,7 @@ yyreduce:
|
|||
case 10:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 127 "config_parser.yy"
|
||||
#line 133 "config_parser.yy"
|
||||
{
|
||||
context->HandleLibrary((yyvsp[(2) - (2)].text));
|
||||
}
|
||||
|
@ -1643,7 +1649,7 @@ yyreduce:
|
|||
case 12:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 133 "config_parser.yy"
|
||||
#line 139 "config_parser.yy"
|
||||
{
|
||||
(yyval.text) = (yyvsp[(1) - (1)].text);
|
||||
}
|
||||
|
@ -1652,17 +1658,17 @@ yyreduce:
|
|||
case 13:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 139 "config_parser.yy"
|
||||
#line 145 "config_parser.yy"
|
||||
{
|
||||
String name = String((yyvsp[(3) - (3)].text));
|
||||
m_Type = context->GetTypeByName(name);
|
||||
m_Type = ConfigCompilerContext::GetContext()->GetType(name);
|
||||
|
||||
if (!m_Type) {
|
||||
if ((yyvsp[(1) - (3)].num))
|
||||
throw_exception(invalid_argument("partial type definition for unknown type '" + name + "'"));
|
||||
|
||||
m_Type = boost::make_shared<ConfigType>(name, yylloc);
|
||||
context->AddType(m_Type);
|
||||
ConfigCompilerContext::GetContext()->AddType(m_Type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1670,7 +1676,7 @@ yyreduce:
|
|||
case 14:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 152 "config_parser.yy"
|
||||
#line 158 "config_parser.yy"
|
||||
{
|
||||
TypeRuleList::Ptr ruleList = *(yyvsp[(6) - (6)].variant);
|
||||
m_Type->GetRuleList()->AddRules(ruleList);
|
||||
|
@ -1681,7 +1687,7 @@ yyreduce:
|
|||
case 15:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 160 "config_parser.yy"
|
||||
#line 166 "config_parser.yy"
|
||||
{
|
||||
(yyval.num) = 0;
|
||||
}
|
||||
|
@ -1690,7 +1696,7 @@ yyreduce:
|
|||
case 16:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 164 "config_parser.yy"
|
||||
#line 170 "config_parser.yy"
|
||||
{
|
||||
(yyval.num) = 1;
|
||||
}
|
||||
|
@ -1699,7 +1705,7 @@ yyreduce:
|
|||
case 17:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 170 "config_parser.yy"
|
||||
#line 176 "config_parser.yy"
|
||||
{
|
||||
m_RuleLists.push(boost::make_shared<TypeRuleList>());
|
||||
}
|
||||
|
@ -1708,7 +1714,7 @@ yyreduce:
|
|||
case 18:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 175 "config_parser.yy"
|
||||
#line 181 "config_parser.yy"
|
||||
{
|
||||
(yyval.variant) = new Value(m_RuleLists.top());
|
||||
m_RuleLists.pop();
|
||||
|
@ -1718,7 +1724,7 @@ yyreduce:
|
|||
case 24:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 190 "config_parser.yy"
|
||||
#line 196 "config_parser.yy"
|
||||
{
|
||||
TypeRule rule((yyvsp[(1) - (2)].type), (yyvsp[(2) - (2)].text), TypeRuleList::Ptr(), yylloc);
|
||||
m_RuleLists.top()->AddRule(rule);
|
||||
|
@ -1728,7 +1734,7 @@ yyreduce:
|
|||
case 25:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 195 "config_parser.yy"
|
||||
#line 201 "config_parser.yy"
|
||||
{
|
||||
TypeRule rule((yyvsp[(1) - (3)].type), (yyvsp[(2) - (3)].text), *(yyvsp[(3) - (3)].variant), yylloc);
|
||||
delete (yyvsp[(3) - (3)].variant);
|
||||
|
@ -1739,7 +1745,7 @@ yyreduce:
|
|||
case 27:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 204 "config_parser.yy"
|
||||
#line 210 "config_parser.yy"
|
||||
{
|
||||
m_Type->SetParent((yyvsp[(2) - (2)].text));
|
||||
}
|
||||
|
@ -1748,7 +1754,7 @@ yyreduce:
|
|||
case 32:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 214 "config_parser.yy"
|
||||
#line 220 "config_parser.yy"
|
||||
{
|
||||
(yyval.type) = (yyvsp[(1) - (1)].type);
|
||||
}
|
||||
|
@ -1757,7 +1763,7 @@ yyreduce:
|
|||
case 33:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 220 "config_parser.yy"
|
||||
#line 226 "config_parser.yy"
|
||||
{
|
||||
m_Abstract = false;
|
||||
m_Local = false;
|
||||
|
@ -1767,7 +1773,7 @@ yyreduce:
|
|||
case 34:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 225 "config_parser.yy"
|
||||
#line 231 "config_parser.yy"
|
||||
{
|
||||
m_Item = boost::make_shared<ConfigItemBuilder>(yylloc);
|
||||
m_Item->SetType((yyvsp[(4) - (5)].text));
|
||||
|
@ -1778,7 +1784,7 @@ yyreduce:
|
|||
case 35:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 231 "config_parser.yy"
|
||||
#line 237 "config_parser.yy"
|
||||
{
|
||||
ExpressionList::Ptr exprl = *(yyvsp[(8) - (8)].variant);
|
||||
delete (yyvsp[(8) - (8)].variant);
|
||||
|
@ -1787,7 +1793,7 @@ yyreduce:
|
|||
m_Item->SetLocal(m_Local);
|
||||
m_Item->SetAbstract(m_Abstract);
|
||||
|
||||
context->AddObject(m_Item->Compile());
|
||||
ConfigCompilerContext::GetContext()->AddItem(m_Item->Compile());
|
||||
m_Item.reset();
|
||||
}
|
||||
break;
|
||||
|
@ -1795,7 +1801,7 @@ yyreduce:
|
|||
case 38:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 249 "config_parser.yy"
|
||||
#line 255 "config_parser.yy"
|
||||
{
|
||||
m_Abstract = true;
|
||||
}
|
||||
|
@ -1804,7 +1810,7 @@ yyreduce:
|
|||
case 39:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 253 "config_parser.yy"
|
||||
#line 259 "config_parser.yy"
|
||||
{
|
||||
m_Local = true;
|
||||
}
|
||||
|
@ -1813,7 +1819,7 @@ yyreduce:
|
|||
case 42:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 263 "config_parser.yy"
|
||||
#line 269 "config_parser.yy"
|
||||
{
|
||||
m_Item->AddParent((yyvsp[(1) - (1)].text));
|
||||
free((yyvsp[(1) - (1)].text));
|
||||
|
@ -1823,7 +1829,7 @@ yyreduce:
|
|||
case 45:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 274 "config_parser.yy"
|
||||
#line 280 "config_parser.yy"
|
||||
{
|
||||
m_ExpressionLists.push(boost::make_shared<ExpressionList>());
|
||||
}
|
||||
|
@ -1832,7 +1838,7 @@ yyreduce:
|
|||
case 46:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 279 "config_parser.yy"
|
||||
#line 285 "config_parser.yy"
|
||||
{
|
||||
(yyval.variant) = new Value(m_ExpressionLists.top());
|
||||
m_ExpressionLists.pop();
|
||||
|
@ -1842,7 +1848,7 @@ yyreduce:
|
|||
case 52:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 294 "config_parser.yy"
|
||||
#line 300 "config_parser.yy"
|
||||
{
|
||||
Expression expr((yyvsp[(1) - (3)].text), (yyvsp[(2) - (3)].op), *(yyvsp[(3) - (3)].variant), yylloc);
|
||||
free((yyvsp[(1) - (3)].text));
|
||||
|
@ -1855,7 +1861,7 @@ yyreduce:
|
|||
case 53:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 302 "config_parser.yy"
|
||||
#line 308 "config_parser.yy"
|
||||
{
|
||||
Expression subexpr((yyvsp[(3) - (6)].text), (yyvsp[(5) - (6)].op), *(yyvsp[(6) - (6)].variant), yylloc);
|
||||
free((yyvsp[(3) - (6)].text));
|
||||
|
@ -1874,7 +1880,7 @@ yyreduce:
|
|||
case 54:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 316 "config_parser.yy"
|
||||
#line 322 "config_parser.yy"
|
||||
{
|
||||
Expression expr((yyvsp[(1) - (1)].text), OperatorSet, (yyvsp[(1) - (1)].text), yylloc);
|
||||
free((yyvsp[(1) - (1)].text));
|
||||
|
@ -1886,7 +1892,7 @@ yyreduce:
|
|||
case 59:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 329 "config_parser.yy"
|
||||
#line 335 "config_parser.yy"
|
||||
{
|
||||
(yyval.op) = (yyvsp[(1) - (1)].op);
|
||||
}
|
||||
|
@ -1895,7 +1901,7 @@ yyreduce:
|
|||
case 60:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 335 "config_parser.yy"
|
||||
#line 341 "config_parser.yy"
|
||||
{
|
||||
(yyval.variant) = new Value((yyvsp[(1) - (1)].text));
|
||||
free((yyvsp[(1) - (1)].text));
|
||||
|
@ -1905,7 +1911,7 @@ yyreduce:
|
|||
case 61:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 340 "config_parser.yy"
|
||||
#line 346 "config_parser.yy"
|
||||
{
|
||||
(yyval.variant) = new Value((yyvsp[(1) - (1)].num));
|
||||
}
|
||||
|
@ -1914,7 +1920,7 @@ yyreduce:
|
|||
case 62:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 344 "config_parser.yy"
|
||||
#line 350 "config_parser.yy"
|
||||
{
|
||||
(yyval.variant) = new Value();
|
||||
}
|
||||
|
@ -1923,7 +1929,7 @@ yyreduce:
|
|||
case 64:
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 351 "config_parser.yy"
|
||||
#line 357 "config_parser.yy"
|
||||
{
|
||||
(yyval.variant) = (yyvsp[(1) - (1)].variant);
|
||||
}
|
||||
|
@ -1932,7 +1938,7 @@ yyreduce:
|
|||
|
||||
|
||||
/* Line 1806 of yacc.c */
|
||||
#line 1936 "config_parser.cc"
|
||||
#line 1942 "config_parser.cc"
|
||||
default: break;
|
||||
}
|
||||
/* User semantic actions sometimes alter yychar, and that requires
|
||||
|
@ -2170,6 +2176,6 @@ yyreturn:
|
|||
|
||||
|
||||
/* Line 2067 of yacc.c */
|
||||
#line 355 "config_parser.yy"
|
||||
#line 361 "config_parser.yy"
|
||||
|
||||
|
||||
|
|
|
@ -99,7 +99,13 @@ static ConfigType::Ptr m_Type;
|
|||
|
||||
void ConfigCompiler::Compile(void)
|
||||
{
|
||||
yyparse(this);
|
||||
assert(ConfigCompilerContext::GetContext() != NULL);
|
||||
|
||||
try {
|
||||
yyparse(this);
|
||||
} catch (const exception& ex) {
|
||||
ConfigCompilerContext::GetContext()->AddError(false, ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
#define scanner (context->GetScanner())
|
||||
|
@ -138,14 +144,14 @@ identifier: T_IDENTIFIER
|
|||
type: partial_specifier T_TYPE identifier
|
||||
{
|
||||
String name = String($3);
|
||||
m_Type = context->GetTypeByName(name);
|
||||
m_Type = ConfigCompilerContext::GetContext()->GetType(name);
|
||||
|
||||
if (!m_Type) {
|
||||
if ($1)
|
||||
throw_exception(invalid_argument("partial type definition for unknown type '" + name + "'"));
|
||||
|
||||
m_Type = boost::make_shared<ConfigType>(name, yylloc);
|
||||
context->AddType(m_Type);
|
||||
ConfigCompilerContext::GetContext()->AddType(m_Type);
|
||||
}
|
||||
}
|
||||
type_inherits_specifier typerulelist
|
||||
|
@ -236,7 +242,7 @@ object_inherits_specifier expressionlist
|
|||
m_Item->SetLocal(m_Local);
|
||||
m_Item->SetAbstract(m_Abstract);
|
||||
|
||||
context->AddObject(m_Item->Compile());
|
||||
ConfigCompilerContext::GetContext()->AddItem(m_Item->Compile());
|
||||
m_Item.reset();
|
||||
}
|
||||
;
|
||||
|
|
|
@ -71,33 +71,6 @@ void *ConfigCompiler::GetScanner(void) const
|
|||
return m_Scanner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the result from the compiler.
|
||||
*
|
||||
* @returns A list of configuration items.
|
||||
*/
|
||||
vector<ConfigItem::Ptr> ConfigCompiler::GetResultObjects(void) const
|
||||
{
|
||||
return m_ResultObjects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the resulting type objects from the compiler.
|
||||
*
|
||||
* @returns A list of type objects.
|
||||
*/
|
||||
vector<ConfigType::Ptr> ConfigCompiler::GetResultTypes(void) const
|
||||
{
|
||||
vector<ConfigType::Ptr> types;
|
||||
|
||||
ConfigType::Ptr type;
|
||||
BOOST_FOREACH(tie(tuples::ignore, type), m_ResultTypes) {
|
||||
types.push_back(type);
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the path for the input file.
|
||||
*
|
||||
|
@ -125,12 +98,7 @@ void ConfigCompiler::HandleInclude(const String& include, bool search, const Deb
|
|||
else
|
||||
path = Utility::DirName(GetPath()) + "/" + include;
|
||||
|
||||
vector<ConfigType::Ptr> types;
|
||||
m_HandleInclude(path, search, &m_ResultObjects, &types, debuginfo);
|
||||
|
||||
BOOST_FOREACH(const ConfigType::Ptr& type, types) {
|
||||
AddType(type);
|
||||
}
|
||||
m_HandleInclude(path, search, debuginfo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,23 +118,12 @@ void ConfigCompiler::HandleLibrary(const String& library)
|
|||
* @param stream The input stream.
|
||||
* @returns Configuration items.
|
||||
*/
|
||||
void ConfigCompiler::CompileStream(const String& path,
|
||||
istream *stream, vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes)
|
||||
void ConfigCompiler::CompileStream(const String& path, istream *stream)
|
||||
{
|
||||
stream->exceptions(istream::badbit);
|
||||
|
||||
ConfigCompiler ctx(path, stream);
|
||||
ctx.Compile();
|
||||
|
||||
if (resultItems) {
|
||||
vector<ConfigItem::Ptr> items = ctx.GetResultObjects();
|
||||
std::copy(items.begin(), items.end(), std::back_inserter(*resultItems));
|
||||
}
|
||||
|
||||
if (resultTypes) {
|
||||
vector<ConfigType::Ptr> types = ctx.GetResultTypes();
|
||||
std::copy(types.begin(), types.end(), std::back_inserter(*resultTypes));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,8 +132,7 @@ void ConfigCompiler::CompileStream(const String& path,
|
|||
* @param path The path.
|
||||
* @returns Configuration items.
|
||||
*/
|
||||
void ConfigCompiler::CompileFile(const String& path,
|
||||
vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes)
|
||||
void ConfigCompiler::CompileFile(const String& path)
|
||||
{
|
||||
ifstream stream;
|
||||
stream.open(path.CStr(), ifstream::in);
|
||||
|
@ -186,7 +142,7 @@ void ConfigCompiler::CompileFile(const String& path,
|
|||
|
||||
Logger::Write(LogInformation, "config", "Compiling config file: " + path);
|
||||
|
||||
return CompileStream(path, &stream, resultItems, resultTypes);
|
||||
return CompileStream(path, &stream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,11 +152,10 @@ void ConfigCompiler::CompileFile(const String& path,
|
|||
* @param text The text.
|
||||
* @returns Configuration items.
|
||||
*/
|
||||
void ConfigCompiler::CompileText(const String& path, const String& text,
|
||||
vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes)
|
||||
void ConfigCompiler::CompileText(const String& path, const String& text)
|
||||
{
|
||||
stringstream stream(text);
|
||||
return CompileStream(path, &stream, resultItems, resultTypes);
|
||||
return CompileStream(path, &stream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -209,12 +164,10 @@ void ConfigCompiler::CompileText(const String& path, const String& text,
|
|||
*
|
||||
* @param include The path from the include directive.
|
||||
* @param search Whether to search include dirs.
|
||||
* @param resultItems The resulting items.
|
||||
* @param resultTypes The resulting types.
|
||||
* @param debuginfo Debug information.
|
||||
*/
|
||||
void ConfigCompiler::HandleFileInclude(const String& include, bool search,
|
||||
vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes, const DebugInfo& debuginfo)
|
||||
const DebugInfo& debuginfo)
|
||||
{
|
||||
String includePath = include;
|
||||
|
||||
|
@ -239,23 +192,13 @@ void ConfigCompiler::HandleFileInclude(const String& include, bool search,
|
|||
|
||||
vector<ConfigItem::Ptr> items;
|
||||
|
||||
if (!Utility::Glob(includePath, boost::bind(&ConfigCompiler::CompileFile, _1, resultItems, resultTypes))) {
|
||||
if (!Utility::Glob(includePath, boost::bind(&ConfigCompiler::CompileFile, _1))) {
|
||||
stringstream msgbuf;
|
||||
msgbuf << "Include file '" + include + "' does not exist (or no files found for pattern): " << debuginfo;
|
||||
throw_exception(invalid_argument(msgbuf.str()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an object to the result.
|
||||
*
|
||||
* @param object The configuration item.
|
||||
*/
|
||||
void ConfigCompiler::AddObject(const ConfigItem::Ptr& object)
|
||||
{
|
||||
m_ResultObjects.push_back(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a directory to the list of include search dirs.
|
||||
*
|
||||
|
@ -268,19 +211,3 @@ void ConfigCompiler::AddIncludeSearchDir(const String& dir)
|
|||
m_IncludeSearchDirs.push_back(dir);
|
||||
}
|
||||
|
||||
void ConfigCompiler::AddType(const ConfigType::Ptr& type)
|
||||
{
|
||||
m_ResultTypes[type->GetName()] = type;
|
||||
}
|
||||
|
||||
ConfigType::Ptr ConfigCompiler::GetTypeByName(const String& name) const
|
||||
{
|
||||
map<String, ConfigType::Ptr>::const_iterator it;
|
||||
|
||||
it = m_ResultTypes.find(name);
|
||||
|
||||
if (it == m_ResultTypes.end())
|
||||
return ConfigType::Ptr();
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
|
|
@ -32,8 +32,7 @@ namespace icinga
|
|||
class I2_CONFIG_API ConfigCompiler
|
||||
{
|
||||
public:
|
||||
typedef function<void (const String&, bool, vector<ConfigItem::Ptr> *,
|
||||
vector<ConfigType::Ptr> *, const DebugInfo&)> HandleIncludeFunc;
|
||||
typedef function<void (const String&, bool, const DebugInfo&)> HandleIncludeFunc;
|
||||
|
||||
ConfigCompiler(const String& path, istream *input = &cin,
|
||||
HandleIncludeFunc includeHandler = &ConfigCompiler::HandleFileInclude);
|
||||
|
@ -41,32 +40,21 @@ public:
|
|||
|
||||
void Compile(void);
|
||||
|
||||
static void CompileStream(const String& path,
|
||||
istream *stream, vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes);
|
||||
static void CompileFile(const String& path, vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes);
|
||||
static void CompileText(const String& path,
|
||||
const String& text, vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes);
|
||||
static void CompileStream(const String& path, istream *stream);
|
||||
static void CompileFile(const String& path);
|
||||
static void CompileText(const String& path, const String& text);
|
||||
|
||||
static void AddIncludeSearchDir(const String& dir);
|
||||
|
||||
vector<ConfigItem::Ptr> GetResultObjects(void) const;
|
||||
vector<ConfigType::Ptr> GetResultTypes(void) const;
|
||||
|
||||
String GetPath(void) const;
|
||||
|
||||
static void HandleFileInclude(const String& include, bool search,
|
||||
vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes,
|
||||
const DebugInfo& debuginfo);
|
||||
|
||||
/* internally used methods */
|
||||
void HandleInclude(const String& include, bool search, const DebugInfo& debuginfo);
|
||||
void HandleLibrary(const String& library);
|
||||
|
||||
void AddObject(const ConfigItem::Ptr& object);
|
||||
void AddType(const ConfigType::Ptr& type);
|
||||
|
||||
ConfigType::Ptr GetTypeByName(const String& name) const;
|
||||
|
||||
size_t ReadInput(char *buffer, size_t max_bytes);
|
||||
void *GetScanner(void) const;
|
||||
|
||||
|
@ -77,8 +65,6 @@ private:
|
|||
HandleIncludeFunc m_HandleInclude;
|
||||
|
||||
void *m_Scanner;
|
||||
vector<ConfigItem::Ptr> m_ResultObjects;
|
||||
map<String, ConfigType::Ptr> m_ResultTypes;
|
||||
|
||||
static vector<String> m_IncludeSearchDirs;
|
||||
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012 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 "i2-config.h"
|
||||
|
||||
using std::ifstream;
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
ConfigCompilerContext *ConfigCompilerContext::m_Context = NULL;
|
||||
|
||||
ConfigCompilerContext::ConfigCompilerContext(void)
|
||||
: m_Flags(0)
|
||||
{ }
|
||||
|
||||
void ConfigCompilerContext::AddItem(const ConfigItem::Ptr& item)
|
||||
{
|
||||
m_Items.push_back(item);
|
||||
m_ItemsMap[make_pair(item->GetType(), item->GetName())] = item;
|
||||
}
|
||||
|
||||
ConfigItem::Ptr ConfigCompilerContext::GetItem(const String& type, const String& name) const
|
||||
{
|
||||
map<pair<String, String>, ConfigItem::Ptr>::const_iterator it;
|
||||
|
||||
it = m_ItemsMap.find(make_pair(type, name));
|
||||
|
||||
if (it == m_ItemsMap.end())
|
||||
return ConfigItem::Ptr();
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
vector<ConfigItem::Ptr> ConfigCompilerContext::GetItems(void) const
|
||||
{
|
||||
return m_Items;
|
||||
}
|
||||
|
||||
void ConfigCompilerContext::AddType(const ConfigType::Ptr& type)
|
||||
{
|
||||
m_Types[type->GetName()] = type;
|
||||
}
|
||||
|
||||
ConfigType::Ptr ConfigCompilerContext::GetType(const String& name) const
|
||||
{
|
||||
map<String, ConfigType::Ptr>::const_iterator it;
|
||||
|
||||
it = m_Types.find(name);
|
||||
|
||||
if (it == m_Types.end())
|
||||
return ConfigType::Ptr();
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void ConfigCompilerContext::AddError(bool warning, const String& message)
|
||||
{
|
||||
m_Errors.push_back(ConfigCompilerError(warning, message));
|
||||
}
|
||||
|
||||
vector<ConfigCompilerError> ConfigCompilerContext::GetErrors(void) const
|
||||
{
|
||||
return m_Errors;
|
||||
}
|
||||
|
||||
void ConfigCompilerContext::SetFlags(int flags)
|
||||
{
|
||||
m_Flags = flags;
|
||||
}
|
||||
|
||||
int ConfigCompilerContext::GetFlags(void) const
|
||||
{
|
||||
return m_Flags;
|
||||
}
|
||||
|
||||
void ConfigCompilerContext::SetContext(ConfigCompilerContext *context)
|
||||
{
|
||||
assert(m_Context == NULL || context == NULL);
|
||||
|
||||
m_Context = context;
|
||||
}
|
||||
|
||||
ConfigCompilerContext *ConfigCompilerContext::GetContext(void)
|
||||
{
|
||||
return m_Context;
|
||||
}
|
||||
|
||||
void ConfigCompilerContext::Validate(void)
|
||||
{
|
||||
SetContext(this);
|
||||
|
||||
BOOST_FOREACH(const ConfigItem::Ptr& item, m_Items) {
|
||||
ConfigType::Ptr ctype = GetType(item->GetType());
|
||||
|
||||
if (!ctype)
|
||||
continue;
|
||||
|
||||
ctype->ValidateItem(item);
|
||||
}
|
||||
|
||||
SetContext(NULL);
|
||||
}
|
||||
|
||||
void ConfigCompilerContext::ActivateItems(void)
|
||||
{
|
||||
assert(m_Context == NULL);
|
||||
|
||||
Logger::Write(LogInformation, "config", "Executing config items...");
|
||||
BOOST_FOREACH(const ConfigItem::Ptr& item, m_Items) {
|
||||
item->Commit();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012 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 CONFIGCOMPILERCONTEXT_H
|
||||
#define CONFIGCOMPILERCONTEXT_H
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*/
|
||||
enum ConfigCompilerFlag
|
||||
{
|
||||
CompilerStrict = 1, /**< Treat warnings as errors. */
|
||||
CompilerLinkExisting = 2 /**< Link objects to existing config items. */
|
||||
};
|
||||
|
||||
struct ConfigCompilerError
|
||||
{
|
||||
bool Warning;
|
||||
String Message;
|
||||
|
||||
ConfigCompilerError(bool warning, const String& message)
|
||||
: Warning(warning), Message(message)
|
||||
{ }
|
||||
};
|
||||
|
||||
/*
|
||||
* @ingroup config
|
||||
*/
|
||||
class ConfigCompilerContext
|
||||
{
|
||||
public:
|
||||
ConfigCompilerContext(void);
|
||||
|
||||
void AddItem(const ConfigItem::Ptr& item);
|
||||
ConfigItem::Ptr GetItem(const String& type, const String& name) const;
|
||||
vector<ConfigItem::Ptr> GetItems(void) const;
|
||||
|
||||
void AddType(const ConfigType::Ptr& type);
|
||||
ConfigType::Ptr GetType(const String& name) const;
|
||||
|
||||
void AddError(bool warning, const String& message);
|
||||
vector<ConfigCompilerError> GetErrors(void) const;
|
||||
|
||||
void SetFlags(int flags);
|
||||
int GetFlags(void) const;
|
||||
|
||||
void Validate(void);
|
||||
void ActivateItems(void);
|
||||
|
||||
static void SetContext(ConfigCompilerContext *context);
|
||||
static ConfigCompilerContext *GetContext(void);
|
||||
|
||||
private:
|
||||
int m_Flags;
|
||||
|
||||
vector<shared_ptr<ConfigItem> > m_Items;
|
||||
map<pair<String, String>, shared_ptr<ConfigItem> > m_ItemsMap;
|
||||
|
||||
map<String, shared_ptr<ConfigType> > m_Types;
|
||||
|
||||
vector<ConfigCompilerError> m_Errors;
|
||||
|
||||
static ConfigCompilerContext *m_Context;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* CONFIGCOMPILERCONTEXT_H */
|
|
@ -92,6 +92,13 @@ vector<String> ConfigItem::GetParents(void) const
|
|||
return m_Parents;
|
||||
}
|
||||
|
||||
Dictionary::Ptr ConfigItem::Link(void) const
|
||||
{
|
||||
Dictionary::Ptr attrs = boost::make_shared<Dictionary>();
|
||||
InternalLink(attrs);
|
||||
return attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the object's properties based on parent objects and the object's
|
||||
* expression list.
|
||||
|
@ -99,7 +106,7 @@ vector<String> ConfigItem::GetParents(void) const
|
|||
* @param dictionary The dictionary that should be used to store the
|
||||
* properties.
|
||||
*/
|
||||
void ConfigItem::CalculateProperties(const Dictionary::Ptr& dictionary) const
|
||||
void ConfigItem::InternalLink(const Dictionary::Ptr& dictionary) const
|
||||
{
|
||||
BOOST_FOREACH(const String& name, m_Parents) {
|
||||
ConfigItem::Ptr parent = ConfigItem::GetObject(GetType(), name);
|
||||
|
@ -111,7 +118,7 @@ void ConfigItem::CalculateProperties(const Dictionary::Ptr& dictionary) const
|
|||
throw_exception(domain_error(message.str()));
|
||||
}
|
||||
|
||||
parent->CalculateProperties(dictionary);
|
||||
parent->InternalLink(dictionary);
|
||||
}
|
||||
|
||||
m_ExpressionList->Execute(dictionary);
|
||||
|
@ -129,8 +136,7 @@ DynamicObject::Ptr ConfigItem::Commit(void)
|
|||
|
||||
DynamicObject::Ptr dobj = m_DynamicObject.lock();
|
||||
|
||||
Dictionary::Ptr properties = boost::make_shared<Dictionary>();
|
||||
CalculateProperties(properties);
|
||||
Dictionary::Ptr properties = Link();
|
||||
|
||||
/* Create a fake update in the format that
|
||||
* DynamicObject::ApplyUpdate expects. */
|
||||
|
@ -279,12 +285,27 @@ DynamicObject::Ptr ConfigItem::GetDynamicObject(void) const
|
|||
ConfigItem::Ptr ConfigItem::GetObject(const String& type, const String& name)
|
||||
{
|
||||
ConfigItem::ItemMap::iterator it;
|
||||
|
||||
ConfigCompilerContext *context = ConfigCompilerContext::GetContext();
|
||||
|
||||
if (context) {
|
||||
ConfigItem::Ptr item = context->GetItem(type, name);
|
||||
|
||||
if (item)
|
||||
return item;
|
||||
|
||||
/* ignore already active objects while we're in the compiler
|
||||
* context and linking to existing items is disabled. */
|
||||
if ((context->GetFlags() & CompilerLinkExisting) == 0)
|
||||
return ConfigItem::Ptr();
|
||||
}
|
||||
|
||||
it = m_Items.find(make_pair(type, name));
|
||||
|
||||
if (it == m_Items.end())
|
||||
return ConfigItem::Ptr();
|
||||
if (it != m_Items.end())
|
||||
return it->second;
|
||||
|
||||
return it->second;
|
||||
return ConfigItem::Ptr();
|
||||
}
|
||||
|
||||
void ConfigItem::Dump(ostream& fp) const
|
||||
|
|
|
@ -54,6 +54,8 @@ public:
|
|||
|
||||
DebugInfo GetDebugInfo(void) const;
|
||||
|
||||
Dictionary::Ptr Link(void) const;
|
||||
|
||||
static ConfigItem::Ptr GetObject(const String& type,
|
||||
const String& name);
|
||||
|
||||
|
@ -61,7 +63,7 @@ public:
|
|||
static boost::signal<void (const ConfigItem::Ptr&)> OnRemoved;
|
||||
|
||||
private:
|
||||
void CalculateProperties(const Dictionary::Ptr& dictionary) const;
|
||||
void InternalLink(const Dictionary::Ptr& dictionary) const;
|
||||
|
||||
void RegisterChild(const ConfigItem::Ptr& child);
|
||||
void UnregisterChild(const ConfigItem::Ptr& child);
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
using namespace icinga;
|
||||
|
||||
ConfigType::TypeMap ConfigType::m_Types;
|
||||
|
||||
ConfigType::ConfigType(const String& name, const DebugInfo& debuginfo)
|
||||
: m_Name(name), m_RuleList(boost::make_shared<TypeRuleList>()), m_DebugInfo(debuginfo)
|
||||
{ }
|
||||
|
@ -52,68 +50,77 @@ DebugInfo ConfigType::GetDebugInfo(void) const
|
|||
return m_DebugInfo;
|
||||
}
|
||||
|
||||
void ConfigType::ValidateObject(const DynamicObject::Ptr& object) const
|
||||
void ConfigType::ValidateItem(const ConfigItem::Ptr& object) const
|
||||
{
|
||||
DynamicObject::AttributeConstIterator it;
|
||||
const DynamicObject::AttributeMap& attributes = object->GetAttributes();
|
||||
|
||||
for (it = attributes.begin(); it != attributes.end(); it++) {
|
||||
if ((it->second.Type & Attribute_Config) == 0)
|
||||
continue;
|
||||
Dictionary::Ptr attrs = object->Link();
|
||||
|
||||
if (!ValidateAttribute(it->first, it->second.Data))
|
||||
Logger::Write(LogWarning, "config", "Configuration attribute '" + it->first +
|
||||
"' on object '" + object->GetName() + "' of type '" + object->GetType()->GetName() + "' is unknown or contains an invalid type.");
|
||||
vector<String> locations;
|
||||
locations.push_back("Object '" + object->GetName() + "' (Type: '" + object->GetType() + "')");
|
||||
|
||||
ConfigType::Ptr parent;
|
||||
if (m_Parent.IsEmpty()) {
|
||||
if (GetName() != "DynamicObject")
|
||||
parent = ConfigCompilerContext::GetContext()->GetType("DynamicObject");
|
||||
} else {
|
||||
parent = ConfigCompilerContext::GetContext()->GetType(m_Parent);
|
||||
}
|
||||
|
||||
vector<TypeRuleList::Ptr> ruleLists;
|
||||
if (parent)
|
||||
ruleLists.push_back(parent->m_RuleList);
|
||||
|
||||
ruleLists.push_back(m_RuleList);
|
||||
|
||||
ValidateDictionary(attrs, ruleLists, locations);
|
||||
}
|
||||
|
||||
void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary, const TypeRuleList::Ptr& ruleList)
|
||||
void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary,
|
||||
const vector<TypeRuleList::Ptr>& ruleLists, vector<String>& locations)
|
||||
{
|
||||
String key;
|
||||
Value value;
|
||||
BOOST_FOREACH(tie(key, value), dictionary) {
|
||||
// TODO: implement (#3619)
|
||||
TypeValidationResult overallResult = ValidationUnknownField;
|
||||
vector<TypeRuleList::Ptr> subRuleLists;
|
||||
|
||||
locations.push_back("Attribute '" + key + "'");
|
||||
|
||||
BOOST_FOREACH(const TypeRuleList::Ptr& ruleList, ruleLists) {
|
||||
TypeRuleList::Ptr subRuleList;
|
||||
TypeValidationResult result = ruleList->Validate(key, value, &subRuleList);
|
||||
|
||||
if (subRuleList)
|
||||
subRuleLists.push_back(subRuleList);
|
||||
|
||||
if (result == ValidationOK) {
|
||||
overallResult = result;
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == ValidationInvalidType)
|
||||
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);
|
||||
else if (overallResult == ValidationInvalidType)
|
||||
ConfigCompilerContext::GetContext()->AddError(false, "Invalid type for attribute: " + stack);
|
||||
|
||||
if (subRuleLists.size() > 0 && value.IsObjectType<Dictionary>())
|
||||
ValidateDictionary(value, subRuleLists, locations);
|
||||
|
||||
locations.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
bool ConfigType::ValidateAttribute(const String& name, const Value& value) const
|
||||
{
|
||||
ConfigType::Ptr parent;
|
||||
|
||||
if (m_Parent.IsEmpty()) {
|
||||
if (GetName() != "DynamicObject")
|
||||
parent = ConfigType::GetByName("DynamicObject");
|
||||
} else {
|
||||
parent = ConfigType::GetByName(m_Parent);
|
||||
}
|
||||
|
||||
if (parent && parent->ValidateAttribute(name, value))
|
||||
return true;
|
||||
|
||||
TypeRuleList::Ptr subRules;
|
||||
|
||||
if (!m_RuleList->FindMatch(name, value, &subRules))
|
||||
return false;
|
||||
|
||||
if (subRules && value.IsObjectType<Dictionary>())
|
||||
ValidateDictionary(value, subRules);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConfigType::Commit(void)
|
||||
{
|
||||
m_Types[GetName()] = GetSelf();
|
||||
}
|
||||
|
||||
ConfigType::Ptr ConfigType::GetByName(const String& name)
|
||||
{
|
||||
ConfigType::TypeMap::iterator it;
|
||||
|
||||
it = m_Types.find(name);
|
||||
|
||||
if (it == m_Types.end())
|
||||
return ConfigType::Ptr();
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
namespace icinga
|
||||
{
|
||||
|
||||
struct ConfigCompilerContext;
|
||||
|
||||
/**
|
||||
* A configuration type. Used to validate config objects.
|
||||
*
|
||||
|
@ -40,16 +42,12 @@ public:
|
|||
String GetParent(void) const;
|
||||
void SetParent(const String& parent);
|
||||
|
||||
void Commit(void);
|
||||
|
||||
TypeRuleList::Ptr GetRuleList(void) const;
|
||||
|
||||
DebugInfo GetDebugInfo(void) const;
|
||||
|
||||
void ValidateObject(const DynamicObject::Ptr& object) const;
|
||||
void ValidateItem(const ConfigItem::Ptr& object) const;
|
||||
|
||||
static ConfigType::Ptr GetByName(const String& name);
|
||||
|
||||
private:
|
||||
String m_Name; /**< The type name. */
|
||||
String m_Parent; /**< The parent type. */
|
||||
|
@ -57,11 +55,8 @@ private:
|
|||
TypeRuleList::Ptr m_RuleList;
|
||||
DebugInfo m_DebugInfo; /**< Debug information. */
|
||||
|
||||
typedef map<String, ConfigType::Ptr> TypeMap;
|
||||
static TypeMap m_Types; /**< All registered configuration types. */
|
||||
|
||||
bool ValidateAttribute(const String& name, const Value& value) const;
|
||||
static void ValidateDictionary(const Dictionary::Ptr& dictionary, const TypeRuleList::Ptr& ruleList);
|
||||
static void ValidateDictionary(const Dictionary::Ptr& dictionary,
|
||||
const vector<TypeRuleList::Ptr>& ruleLists, vector<String>& locations);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -48,11 +48,12 @@ using std::endl;
|
|||
#include "debuginfo.h"
|
||||
#include "typerulelist.h"
|
||||
#include "typerule.h"
|
||||
#include "configtype.h"
|
||||
#include "expression.h"
|
||||
#include "expressionlist.h"
|
||||
#include "configitem.h"
|
||||
#include "configtype.h"
|
||||
#include "configitembuilder.h"
|
||||
#include "configcompiler.h"
|
||||
#include "configcompilercontext.h"
|
||||
|
||||
#endif /* I2CONFIG_H */
|
||||
|
|
|
@ -31,11 +31,13 @@ TypeRuleList::Ptr TypeRule::GetSubRules(void) const
|
|||
return m_SubRules;
|
||||
}
|
||||
|
||||
bool TypeRule::Matches(const String& name, const Value& value) const
|
||||
bool TypeRule::MatchName(const String& name) const
|
||||
{
|
||||
if (!Utility::Match(m_NamePattern, name))
|
||||
return false;
|
||||
return (Utility::Match(m_NamePattern, name));
|
||||
}
|
||||
|
||||
bool TypeRule::MatchValue(const Value& value) const
|
||||
{
|
||||
if (value.IsEmpty())
|
||||
return true;
|
||||
|
||||
|
@ -64,3 +66,4 @@ bool TypeRule::Matches(const String& name, const Value& value) const
|
|||
assert(!"Type rule has invalid type specifier.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,8 @@ public:
|
|||
|
||||
TypeRuleList::Ptr GetSubRules(void) const;
|
||||
|
||||
bool Matches(const String& name, const Value& value) const;
|
||||
bool MatchName(const String& name) const;
|
||||
bool MatchValue(const Value& value) const;
|
||||
|
||||
private:
|
||||
TypeSpecifier m_Type;
|
||||
|
|
|
@ -54,20 +54,31 @@ size_t TypeRuleList::GetLength(void) const
|
|||
}
|
||||
|
||||
/**
|
||||
* Finds a matching rule.
|
||||
* Validates a field.
|
||||
*
|
||||
* @param name The name of the attribute.
|
||||
* @param value The value of the attribute.
|
||||
* *@param[out] subRules The list of sub-rules for the matching rule.
|
||||
* @param[out] subRules The list of sub-rules for the matching rule.
|
||||
* @returns The validation result.
|
||||
*/
|
||||
bool TypeRuleList::FindMatch(const String& name, const Value& value, TypeRuleList::Ptr *subRules)
|
||||
TypeValidationResult TypeRuleList::Validate(const String& name, const Value& value, TypeRuleList::Ptr *subRules) const
|
||||
{
|
||||
bool foundField = false;
|
||||
BOOST_FOREACH(const TypeRule& rule, m_Rules) {
|
||||
if (rule.Matches(name, value)) {
|
||||
if (!rule.MatchName(name))
|
||||
continue;
|
||||
|
||||
foundField = true;
|
||||
|
||||
if (rule.MatchValue(value)) {
|
||||
*subRules = rule.GetSubRules();
|
||||
return true;
|
||||
return ValidationOK;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
if (foundField)
|
||||
return ValidationInvalidType;
|
||||
else
|
||||
return ValidationUnknownField;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,16 @@ namespace icinga
|
|||
|
||||
struct TypeRule;
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*/
|
||||
enum TypeValidationResult
|
||||
{
|
||||
ValidationOK,
|
||||
ValidationInvalidType,
|
||||
ValidationUnknownField
|
||||
};
|
||||
|
||||
/**
|
||||
* A list of configuration type rules.
|
||||
*
|
||||
|
@ -39,7 +49,7 @@ public:
|
|||
void AddRule(const TypeRule& rule);
|
||||
void AddRules(const TypeRuleList::Ptr& ruleList);
|
||||
|
||||
bool FindMatch(const String& name, const Value& value, TypeRuleList::Ptr *subRules);
|
||||
TypeValidationResult Validate(const String& name, const Value& value, TypeRuleList::Ptr *subRules) const;
|
||||
|
||||
size_t GetLength(void) const;
|
||||
|
||||
|
|
Loading…
Reference in New Issue