Implicitly set zone attribute for files includes from zones.d.

Refs #6191
This commit is contained in:
Gunnar Beutner 2014-05-13 14:40:12 +02:00
parent c089b7950d
commit 3a1ce23aeb
7 changed files with 59 additions and 50 deletions

View File

@ -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

View File

@ -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 */
}

View File

@ -123,6 +123,8 @@ public:
static tm LocalTime(time_t ts);
static bool PathExists(const String& path);
private:
Utility(void);

View File

@ -216,7 +216,6 @@ static std::stack<TypeRuleList::Ptr> 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<Dictionary>();
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>(&AExpression::OpObject, args, exprl, DebugInfoRange(@2, @5)));

View File

@ -38,9 +38,10 @@ std::vector<String> 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<ConfigItem::Ptr> 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);
}
/**

View File

@ -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;

View File

@ -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)