]> granicus.if.org Git - icinga2/commitdiff
Fix: Names for nested objects are evaluated at the wrong time
authorGunnar Beutner <gunnar.beutner@netways.de>
Sat, 15 Nov 2014 14:57:23 +0000 (15:57 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Sat, 15 Nov 2014 14:57:56 +0000 (15:57 +0100)
fixes #7689

lib/config/configitem.cpp
lib/config/configitem.hpp
lib/config/configtype.cpp

index 2ac90c1528074b5f206e94edc7464cebaea5f052..0b48c8a814b3d80c938576da60e4fc5f0ef14700 100644 (file)
@@ -151,11 +151,12 @@ DynamicObject::Ptr ConfigItem::Commit(bool discard)
        Dictionary::Ptr locals = new Dictionary();
        locals->Set("__parent", m_Scope);
        m_Scope.reset();
-       locals->Set("name", m_Name);
 
        dobj->SetParentScope(locals);
        locals.reset();
 
+       dobj->SetName(m_Name);
+
        DebugHint debugHints;
 
        try {
@@ -269,52 +270,59 @@ ConfigItem::Ptr ConfigItem::GetObject(const String& type, const String& name)
        return ConfigItem::Ptr();
 }
 
-bool ConfigItem::ValidateItems(void)
+bool ConfigItem::CommitNewItems(void)
 {
-       if (ConfigCompilerContext::GetInstance()->HasErrors())
-               return false;
+       std::vector<ConfigItem::Ptr> items;
 
-       ParallelWorkQueue upq;
+       do {
+               ParallelWorkQueue upq;
 
-       Log(LogInformation, "ConfigItem", "Committing config items");
+               items.clear();
 
-       BOOST_FOREACH(const ItemMap::value_type& kv, m_Items) {
-               upq.Enqueue(boost::bind(&ConfigItem::Commit, kv.second, false));
-       }
+               {
+                       boost::mutex::scoped_lock lock(m_Mutex);
 
-       BOOST_FOREACH(const ConfigItem::Ptr& item, m_UnnamedItems) {
-               upq.Enqueue(boost::bind(&ConfigItem::Commit, item, true));
-       }
+                       BOOST_FOREACH(const ItemMap::value_type& kv, m_Items) {
+                               if (!kv.second->m_Abstract && !kv.second->m_Object) {
+                                       upq.Enqueue(boost::bind(&ConfigItem::Commit, kv.second, false));
+                                       items.push_back(kv.second);
+                               }
+                       }
 
-       upq.Join();
+                       BOOST_FOREACH(const ConfigItem::Ptr& item, m_UnnamedItems) {
+                               if (!item->m_Abstract && !item->m_Object) {
+                                       upq.Enqueue(boost::bind(&ConfigItem::Commit, item, true));
+                                       items.push_back(item);
+                               }
+                       }
 
-       if (ConfigCompilerContext::GetInstance()->HasErrors())
-               return false;
+                       m_UnnamedItems.clear();
+               }
 
-       std::vector<DynamicObject::Ptr> objects;
-       BOOST_FOREACH(const ItemMap::value_type& kv, m_Items) {
-               DynamicObject::Ptr object = kv.second->m_Object;
+               upq.Join();
 
-               if (object)
-                       objects.push_back(object);
-       }
+               if (ConfigCompilerContext::GetInstance()->HasErrors())
+                       return false;
 
-       BOOST_FOREACH(const ConfigItem::Ptr& item, m_UnnamedItems) {
-               DynamicObject::Ptr object = item->m_Object;
+               BOOST_FOREACH(const ConfigItem::Ptr& item, items) {
+                       upq.Enqueue(boost::bind(&DynamicObject::OnConfigLoaded, item->m_Object));
+               }
 
-               if (object)
-                       objects.push_back(object);
-       }
+               upq.Join();
+       } while (!items.empty());
 
-       m_UnnamedItems.clear();
+       return true;
+}
 
-       Log(LogInformation, "ConfigItem", "Triggering OnConfigLoaded signal for config items");
+bool ConfigItem::ValidateItems(void)
+{
+       if (ConfigCompilerContext::GetInstance()->HasErrors())
+               return false;
 
-       BOOST_FOREACH(const DynamicObject::Ptr& object, objects) {
-               upq.Enqueue(boost::bind(&DynamicObject::OnConfigLoaded, object));
-       }
+       Log(LogInformation, "ConfigItem", "Committing config items");
 
-       upq.Join();
+       if (!CommitNewItems())
+               return false;
 
        Log(LogInformation, "ConfigItem", "Evaluating 'object' rules (step 1)...");
        ObjectRule::EvaluateRules(false);
@@ -322,11 +330,12 @@ bool ConfigItem::ValidateItems(void)
        Log(LogInformation, "ConfigItem", "Evaluating 'apply' rules...");
        ApplyRule::EvaluateRules(true);
 
+       if (!CommitNewItems())
+               return false;
+
        Log(LogInformation, "ConfigItem", "Evaluating 'object' rules (step 2)...");
        ObjectRule::EvaluateRules(true);
 
-       upq.Join();
-
        ConfigItem::DiscardItems();
        ConfigType::DiscardTypes();
 
index b3b1ad7ddd8009127758e4db363c0dd9833e9d2c..390f8ce72fb4d39a80d36a83c26de49bcb9a4220 100644 (file)
@@ -87,6 +87,8 @@ private:
 
        static ConfigItem::Ptr GetObjectUnlocked(const String& type,
            const String& name);
+
+       static bool CommitNewItems(void);
 };
 
 }
index dcd07d9c2cabc581436a6e451b568cef87f59e80..9970a440c44a89f382fca876c1666cd2e67198b1 100644 (file)
@@ -115,7 +115,7 @@ void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary,
 
                        Value value = dictionary->Get(require);
 
-                       if (value.IsEmpty()) {
+                       if (value.IsEmpty() || (value.IsString() && static_cast<String>(value).IsEmpty())) {
                                ConfigCompilerContext::GetInstance()->AddMessage(true,
                                    "Required attribute is missing: " + LocationToString(locations));
                        }