From 3a1ce23aeb6d0479df4290ad065d4a9336216912 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 13 May 2014 14:40:12 +0200 Subject: [PATCH] Implicitly set zone attribute for files includes from zones.d. Refs #6191 --- icinga-app/icinga.cpp | 19 +++++++--------- lib/base/utility.cpp | 11 ++++++++++ lib/base/utility.h | 2 ++ lib/config/config_parser.yy | 17 ++++++-------- lib/config/configcompiler.cpp | 39 +++++++++++++++++++-------------- lib/config/configcompiler.h | 12 ++++++---- lib/remote/apilistener-sync.cpp | 9 +------- 7 files changed, 59 insertions(+), 50 deletions(-) diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index 88e548129..eed73d86f 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -65,25 +65,20 @@ static String LoadAppType(const String& typeSpec) return typeSpec.SubStr(index + 1); } -static void IncludeDirRecursive(const String& path) +static void IncludeZoneDirRecursive(const String& path) { - Utility::GlobRecursive(path, "*.conf", &ConfigCompiler::CompileFile, GlobFile); + String zoneName = Utility::BaseName(path); + Utility::GlobRecursive(path, "*.conf", boost::bind(&ConfigCompiler::CompileFile, _1, zoneName), GlobFile); } static void IncludeNonLocalZone(const String& zonePath) { String etcPath = Application::GetZonesDir() + "/" + Utility::BaseName(zonePath); -#ifndef _WIN32 - struct stat statbuf; - if (lstat(etcPath.CStr(), &statbuf) >= 0) -#else /* _WIN32 */ - struct _stat statbuf; - if (_stat(etcPath.CStr(), &statbuf) >= 0) -#endif /* _WIN32 */ + if (Utility::PathExists(etcPath)) return; - IncludeDirRecursive(zonePath); + IncludeZoneDirRecursive(zonePath); } static bool LoadConfigFiles(const String& appType) @@ -96,7 +91,9 @@ static bool LoadConfigFiles(const String& appType) } } - IncludeDirRecursive(Application::GetZonesDir()); + String zonesDir = Application::GetZonesDir(); + + Utility::Glob(Application::GetZonesDir() + "/*", &IncludeZoneDirRecursive, GlobDirectory); Utility::Glob(Application::GetLocalStateDir() + "/lib/icinga2/api/zones/*", &IncludeNonLocalZone, GlobDirectory); /* Load cluster config files - this should probably be in libremote but diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp index 14eccb15d..45c1bc577 100644 --- a/lib/base/utility.cpp +++ b/lib/base/utility.cpp @@ -1025,3 +1025,14 @@ tm Utility::LocalTime(time_t ts) return result; #endif /* _MSC_VER */ } + +bool Utility::PathExists(const String& path) +{ +#ifndef _WIN32 + struct stat statbuf; + return (lstat(path.CStr(), &statbuf) >= 0); +#else /* _WIN32 */ + struct _stat statbuf; + return (_stat(path.CStr(), &statbuf) >= 0) +#endif /* _WIN32 */ +} diff --git a/lib/base/utility.h b/lib/base/utility.h index 34c951495..7217f2715 100644 --- a/lib/base/utility.h +++ b/lib/base/utility.h @@ -123,6 +123,8 @@ public: static tm LocalTime(time_t ts); + static bool PathExists(const String& path); + private: Utility(void); diff --git a/lib/config/config_parser.yy b/lib/config/config_parser.yy index 33d50bc12..3f25ec95d 100644 --- a/lib/config/config_parser.yy +++ b/lib/config/config_parser.yy @@ -216,7 +216,6 @@ static std::stack m_RuleLists; static ConfigType::Ptr m_Type; static Dictionary::Ptr m_ModuleScope; -static String m_Zone; static int m_StatementNum; static bool m_Apply; @@ -229,7 +228,6 @@ void ConfigCompiler::Compile(void) { m_ModuleScope = make_shared(); - String parentZone = m_Zone; int parentStatementNum = m_StatementNum; m_StatementNum = 0; @@ -242,7 +240,6 @@ void ConfigCompiler::Compile(void) ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex)); } - m_Zone = parentZone; m_StatementNum = parentStatementNum; } @@ -276,23 +273,23 @@ zone: T_ZONE rterm sep AExpression::Ptr aexpr = *$2; delete $2; - if (!m_Zone.IsEmpty()) + if (!context->GetZone().IsEmpty()) BOOST_THROW_EXCEPTION(std::invalid_argument("Zone name cannot be changed once it's been set.")); if (m_StatementNum != 0) BOOST_THROW_EXCEPTION(std::invalid_argument("'zone' directive must be the first statement in a file.")); - m_Zone = aexpr->Evaluate(m_ModuleScope); + context->SetZone(aexpr->Evaluate(m_ModuleScope)); } | T_ZONE rterm { AExpression::Ptr aexpr = *$2; delete $2; - if (!m_Zone.IsEmpty()) + if (!context->GetZone().IsEmpty()) BOOST_THROW_EXCEPTION(std::invalid_argument("Zone name cannot be changed once it's been set.")); - m_Zone = aexpr->Evaluate(m_ModuleScope); + context->SetZone(aexpr->Evaluate(m_ModuleScope)); } rterm_scope sep { @@ -301,9 +298,9 @@ zone: T_ZONE rterm sep try { ascope->Evaluate(m_ModuleScope); - m_Zone = String(); + context->SetZone(String()); } catch (...) { - m_Zone = String(); + context->SetZone(String()); } } ; @@ -515,7 +512,7 @@ object: args->Add(filter); - args->Add(m_Zone); + args->Add(context->GetZone()); $$ = new Value(make_shared(&AExpression::OpObject, args, exprl, DebugInfoRange(@2, @5))); diff --git a/lib/config/configcompiler.cpp b/lib/config/configcompiler.cpp index 94ceaefc7..7f1c70dda 100644 --- a/lib/config/configcompiler.cpp +++ b/lib/config/configcompiler.cpp @@ -38,9 +38,10 @@ std::vector ConfigCompiler::m_IncludeSearchDirs; * @param path The path of the configuration file (or another name that * identifies the source of the configuration text). * @param input Input stream for the configuration file. + * @param zone The zone. */ -ConfigCompiler::ConfigCompiler(const String& path, std::istream *input) - : m_Path(path), m_Input(input) +ConfigCompiler::ConfigCompiler(const String& path, std::istream *input, const String& zone) + : m_Path(path), m_Input(input), m_Zone(zone) { InitializeScanner(); } @@ -86,6 +87,16 @@ String ConfigCompiler::GetPath(void) const return m_Path; } +void ConfigCompiler::SetZone(const String& zone) +{ + m_Zone = zone; +} + +String ConfigCompiler::GetZone(void) const +{ + return m_Zone; +} + /** * Handles an include directive. * @@ -108,13 +119,7 @@ void ConfigCompiler::HandleInclude(const String& include, bool search, const Deb BOOST_FOREACH(const String& dir, m_IncludeSearchDirs) { String spath = dir + "/" + include; -#ifndef _WIN32 - struct stat statbuf; - if (lstat(spath.CStr(), &statbuf) >= 0) { -#else /* _WIN32 */ - struct _stat statbuf; - if (_stat(spath.CStr(), &statbuf) >= 0) { -#endif /* _WIN32 */ + if (Utility::PathExists(spath)) { includePath = spath; break; } @@ -123,7 +128,7 @@ void ConfigCompiler::HandleInclude(const String& include, bool search, const Deb std::vector items; - if (!Utility::Glob(includePath, boost::bind(&ConfigCompiler::CompileFile, _1), GlobFile) && includePath.FindFirstOf("*?") == String::NPos) { + if (!Utility::Glob(includePath, boost::bind(&ConfigCompiler::CompileFile, _1, m_Zone), GlobFile) && includePath.FindFirstOf("*?") == String::NPos) { std::ostringstream msgbuf; msgbuf << "Include file '" + include + "' does not exist: " << debuginfo; BOOST_THROW_EXCEPTION(std::invalid_argument(msgbuf.str())); @@ -146,7 +151,7 @@ void ConfigCompiler::HandleIncludeRecursive(const String& include, const String& else path = Utility::DirName(GetPath()) + "/" + include; - Utility::GlobRecursive(path, pattern, boost::bind(&ConfigCompiler::CompileFile, _1), GlobFile); + Utility::GlobRecursive(path, pattern, boost::bind(&ConfigCompiler::CompileFile, _1, m_Zone), GlobFile); } /** @@ -166,13 +171,13 @@ void ConfigCompiler::HandleLibrary(const String& library) * @param stream The input stream. * @returns Configuration items. */ -void ConfigCompiler::CompileStream(const String& path, std::istream *stream) +void ConfigCompiler::CompileStream(const String& path, std::istream *stream, const String& zone) { CONTEXT("Compiling configuration stream with name '" + path + "'"); stream->exceptions(std::istream::badbit); - ConfigCompiler ctx(path, stream); + ConfigCompiler ctx(path, stream, zone); ctx.Compile(); } @@ -182,7 +187,7 @@ void ConfigCompiler::CompileStream(const String& path, std::istream *stream) * @param path The path. * @returns Configuration items. */ -void ConfigCompiler::CompileFile(const String& path) +void ConfigCompiler::CompileFile(const String& path, const String& zone) { CONTEXT("Compiling configuration file '" + path + "'"); @@ -197,7 +202,7 @@ void ConfigCompiler::CompileFile(const String& path) Log(LogInformation, "config", "Compiling config file: " + path); - return CompileStream(path, &stream); + return CompileStream(path, &stream, zone); } /** @@ -207,10 +212,10 @@ void ConfigCompiler::CompileFile(const String& path) * @param text The text. * @returns Configuration items. */ -void ConfigCompiler::CompileText(const String& path, const String& text) +void ConfigCompiler::CompileText(const String& path, const String& text, const String& zone) { std::stringstream stream(text); - return CompileStream(path, &stream); + return CompileStream(path, &stream, zone); } /** diff --git a/lib/config/configcompiler.h b/lib/config/configcompiler.h index 59b36a959..b9631dc38 100644 --- a/lib/config/configcompiler.h +++ b/lib/config/configcompiler.h @@ -40,19 +40,22 @@ namespace icinga class I2_CONFIG_API ConfigCompiler { public: - explicit ConfigCompiler(const String& path, std::istream *input); + explicit ConfigCompiler(const String& path, std::istream *input, const String& zone = String()); virtual ~ConfigCompiler(void); void Compile(void); - static void CompileStream(const String& path, std::istream *stream); - static void CompileFile(const String& path); - static void CompileText(const String& path, const String& text); + static void CompileStream(const String& path, std::istream *stream, const String& zone = String()); + static void CompileFile(const String& path, const String& zone = String()); + static void CompileText(const String& path, const String& text, const String& zone = String()); static void AddIncludeSearchDir(const String& dir); String GetPath(void) const; + void SetZone(const String& zone); + String GetZone(void) const; + /* internally used methods */ void HandleInclude(const String& include, bool search, const DebugInfo& debuginfo); void HandleIncludeRecursive(const String& include, const String& pattern, const DebugInfo& debuginfo); @@ -64,6 +67,7 @@ public: private: String m_Path; std::istream *m_Input; + String m_Zone; void *m_Scanner; diff --git a/lib/remote/apilistener-sync.cpp b/lib/remote/apilistener-sync.cpp index 6bfc9e57b..556d1289f 100644 --- a/lib/remote/apilistener-sync.cpp +++ b/lib/remote/apilistener-sync.cpp @@ -28,14 +28,7 @@ using namespace icinga; bool ApiListener::IsConfigMaster(const Zone::Ptr& zone) const { String path = Application::GetZonesDir() + "/" + zone->GetName(); - -#ifndef _WIN32 - struct stat statbuf; - return (lstat(path.CStr(), &statbuf) >= 0); -#else /* _WIN32 */ - struct _stat statbuf; - return (_stat(path.CStr(), &statbuf) >= 0); -#endif /* _WIN32 */ + return Utility::PathExists(path); } void ApiListener::ConfigGlobHandler(const Dictionary::Ptr& config, const String& path, const String& file)