]> granicus.if.org Git - icinga2/commitdiff
Evaluate apply filters in the for loop
authorGunnar Beutner <gunnar@beutner.name>
Thu, 29 Jan 2015 11:38:25 +0000 (12:38 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Thu, 29 Jan 2015 11:38:25 +0000 (12:38 +0100)
fixes #7610

14 files changed:
doc/3-monitoring-basics.md
doc/4-configuring-icinga-2.md
etc/icinga2/conf.d/services.conf
lib/base/dictionary.cpp
lib/base/dictionary.hpp
lib/config/config_parser.yy
lib/icinga/dependency-apply.cpp
lib/icinga/dependency.hpp
lib/icinga/notification-apply.cpp
lib/icinga/notification.hpp
lib/icinga/scheduleddowntime-apply.cpp
lib/icinga/scheduleddowntime.hpp
lib/icinga/service-apply.cpp
lib/icinga/service.hpp

index 4df47d8a532cbedd99dccd075088c72875255de6..3d01e9c987b1e9dfe5f735d8dd722efa439945c3 100644 (file)
@@ -427,8 +427,6 @@ You can also specifiy the check command that way.
       notes = "Interface check for Port " + string(vars.port) + " in VLAN " + vars.vlan + " on Address " + vars.address + " QoS " + vars.qos
       notes_url = "http://foreman.company.com/hosts/" + host.name
       action_url = "http://snmp.checker.company.com/" + host.name + "if-" + if_name
-
-      assign where host.vars.interfaces
     }
 
 Note that numbers must be explicitely casted to string when adding to strings.
@@ -481,8 +479,6 @@ values for any object attribute specified in that apply rule.
 
       notes_url = "http://foreman.company.com/hosts/" + host.name
       action_url = "http://snmp.checker.company.com/" + host.name + "/" + vars.customer_id
-
-      assign where host.vars.hosting
     }
 
 ### <a id="groups"></a> Groups
@@ -1003,8 +999,6 @@ string values for passing multiple partitions to the `check_disk` check plugin.
 
       vars.disk_wfree = 10
       vars.disk_cfree = 5
-
-      assign where host.vars.local_disks
     }
 
 
index d0a06403c7ae5d42bfc6679da0b4c67dea20190d..543f9e22fd6f9dd6cb18172c9f3b96fd566cda22 100644 (file)
@@ -366,8 +366,6 @@ Configuration example:
       check_command = "disk"
 
       vars += config
-
-      assign where host.vars.disks
     }
 
 A similar example is used for the `http` services. That way you can make your
index 4f794b61dc62b728b10ba299b45c7b1a38c437fc..014f07784db84d6d4040048ffe916204dfc57b2e 100644 (file)
@@ -61,8 +61,6 @@ apply Service for (http_vhost => config in host.vars.http_vhosts) {
   check_command = "http"
 
   vars += config
-
-  assign where host.vars.http_vhosts
 }
 
 apply Service for (disk => config in host.vars.disks) {
@@ -71,8 +69,6 @@ apply Service for (disk => config in host.vars.disks) {
   check_command = "disk"
 
   vars += config
-
-  assign where host.vars.disks
 }
 
 apply Service "icinga" {
index 34c2368b39b6dc3d73001a560c1960351f83c7df..509da9565b78f17db31ebc69e0053adac0d8af72 100644 (file)
@@ -215,3 +215,23 @@ Dictionary::Ptr Dictionary::ShallowClone(void) const
        CopyTo(clone);
        return clone;
 }
+
+/**
+ * Returns an array containing all keys
+ * which are currently set in this directory.
+ *
+ * @returns an array of key names
+ */
+std::vector<String> Dictionary::GetKeys(void) const
+{
+       ASSERT(!OwnsLock());
+       ObjectLock olock(this);
+
+       std::vector<String> keys;
+
+       BOOST_FOREACH(const Dictionary::Pair& kv, m_Data) {
+               keys.push_back(kv.first);
+       }
+
+       return keys;
+}
index 10f278c50adb264b1904463fa8c28f8a95d75194..d6fdefdfd84e44a4b42401cab1289afc127043ba 100644 (file)
@@ -25,6 +25,7 @@
 #include "base/value.hpp"
 #include <boost/range/iterator.hpp>
 #include <map>
+#include <vector>
 
 namespace icinga
 {
@@ -64,6 +65,8 @@ public:
        void CopyTo(const Dictionary::Ptr& dest) const;
        Dictionary::Ptr ShallowClone(void) const;
 
+       std::vector<String> GetKeys(void) const;
+
        static Object::Ptr GetPrototype(void);
 
 private:
index 2c1b27b80e2afd0d21e42fb743c58fadea6e1c86..acef893fa94c177edb2f777b98555acdc97cb05d 100644 (file)
@@ -996,16 +996,23 @@ apply:
                DictExpression *exprl = dynamic_cast<DictExpression *>($8);
                exprl->MakeInline();
 
-               // assign && !ignore
-               if (!context->m_SeenAssign.top())
-                       BOOST_THROW_EXCEPTION(ScriptError("'apply' is missing 'assign'", DebugInfoRange(@2, @3)));
-
+               bool seen_assign = context->m_SeenAssign.top();
                context->m_SeenAssign.pop();
 
+               // assign && !ignore
+               if (!seen_assign && !context->m_FTerm.top())
+                       BOOST_THROW_EXCEPTION(ScriptError("'apply' is missing 'assign'/'for'", DebugInfoRange(@2, @3)));
+
                Expression *ignore = context->m_Ignore.top();
                context->m_Ignore.pop();
 
-               Expression *assign = context->m_Assign.top();
+               Expression *assign;
+
+               if (!seen_assign)
+                       assign = MakeLiteral(true);
+               else
+                       assign = context->m_Assign.top();
+
                context->m_Assign.pop();
 
                Expression *filter;
index b3e2065075d170dc1d34751722a2c64c26eae1ee..a16c9c05916f9ff812106a8e2c1411e4e16e83fb 100644 (file)
@@ -41,8 +41,11 @@ void Dependency::RegisterApplyRuleHandler(void)
        ApplyRule::RegisterType("Dependency", targets);
 }
 
-void Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule)
+bool Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule)
 {
+       if (!rule.EvaluateFilter(frame))
+               return false;
+
        DebugInfo di = rule.GetDebugInfo();
 
        Log(LogDebug, "Dependency")
@@ -72,6 +75,8 @@ void Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, cons
 
        ConfigItem::Ptr dependencyItem = builder->Compile();
        dependencyItem->Commit();
+
+       return true;
 }
 
 bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule)
@@ -93,27 +98,32 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
        if (service)
                frame.Locals->Set("service", service);
 
-       if (!rule.EvaluateFilter(frame))
-               return false;
-
        Value vinstances;
 
        if (rule.GetFTerm()) {
-               vinstances = rule.GetFTerm()->Evaluate(frame);
+               try {
+                       vinstances = rule.GetFTerm()->Evaluate(frame);
+               } catch (const std::exception&) {
+                       /* Silently ignore errors here and assume there are no instances. */
+                       return false;
+               }
        } else {
                Array::Ptr instances = new Array();
                instances->Add("");
                vinstances = instances;
        }
 
+       bool match = false;
+
        if (vinstances.IsObjectType<Array>()) {
                if (!rule.GetFVVar().IsEmpty())
                        BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di));
 
                Array::Ptr arr = vinstances;
+               Array::Ptr arrclone = arr->ShallowClone();
 
-               ObjectLock olock(arr);
-               BOOST_FOREACH(const String& instance, arr) {
+               ObjectLock olock(arrclone);
+               BOOST_FOREACH(const String& instance, arrclone) {
                        String name = rule.GetName();
 
                        if (!rule.GetFKVar().IsEmpty()) {
@@ -121,7 +131,8 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
                                name += instance;
                        }
 
-                       EvaluateApplyRuleInstance(checkable, name, frame, rule);
+                       if (EvaluateApplyRuleInstance(checkable, name, frame, rule))
+                               match = true;
                }
        } else if (vinstances.IsObjectType<Dictionary>()) {
                if (rule.GetFVVar().IsEmpty())
@@ -129,16 +140,16 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
        
                Dictionary::Ptr dict = vinstances;
 
-               ObjectLock olock(dict);
-               BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
-                       frame.Locals->Set(rule.GetFKVar(), kv.first);
-                       frame.Locals->Set(rule.GetFVVar(), kv.second);
+               BOOST_FOREACH(const String& key, dict->GetKeys()) {
+                       frame.Locals->Set(rule.GetFKVar(), key);
+                       frame.Locals->Set(rule.GetFVVar(), dict->Get(key));
 
-                       EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule);
+                       if (EvaluateApplyRuleInstance(checkable, rule.GetName() + key, frame, rule))
+                               match = true;
                }
        }
 
-       return true;
+       return match;
 }
 
 void Dependency::EvaluateApplyRules(const Host::Ptr& host)
index fd22742939623d3ba5ec0001a17d4c873329e0b1..6635cb3022a8f96c71daa86004f93e42485a89d3 100644 (file)
@@ -65,7 +65,7 @@ private:
        Checkable::Ptr m_Parent;
        Checkable::Ptr m_Child;
 
-       static void EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule);
+       static bool EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule);
        static bool EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule);
 };
 
index 0fa71587cd6171485e16dda9a24583f211b45e35..b6fe251b49deb2312a5b3772b42c461a8c524b39 100644 (file)
@@ -41,8 +41,11 @@ void Notification::RegisterApplyRuleHandler(void)
        ApplyRule::RegisterType("Notification", targets);
 }
 
-void Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule)
+bool Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule)
 {
+       if (!rule.EvaluateFilter(frame))
+               return false;
+
        DebugInfo di = rule.GetDebugInfo();
 
        Log(LogDebug, "Notification")
@@ -71,6 +74,8 @@ void Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, co
 
        ConfigItem::Ptr notificationItem = builder->Compile();
        notificationItem->Commit();
+
+       return true;
 }
 
 bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule)
@@ -92,19 +97,23 @@ bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const Appl
        if (service)
                frame.Locals->Set("service", service);
 
-       if (!rule.EvaluateFilter(frame))
-               return false;
-
        Value vinstances;
 
        if (rule.GetFTerm()) {
-               vinstances = rule.GetFTerm()->Evaluate(frame);
+               try {
+                       vinstances = rule.GetFTerm()->Evaluate(frame);
+               } catch (const std::exception&) {
+                       /* Silently ignore errors here and assume there are no instances. */
+                       return false;
+               }
        } else {
                Array::Ptr instances = new Array();
                instances->Add("");
                vinstances = instances;
        }
 
+       bool match = false;
+
        if (vinstances.IsObjectType<Array>()) {
                if (!rule.GetFVVar().IsEmpty())
                        BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di));
@@ -120,7 +129,8 @@ bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const Appl
                                name += instance;
                        }
 
-                       EvaluateApplyRuleInstance(checkable, name, frame, rule);
+                       if (EvaluateApplyRuleInstance(checkable, name, frame, rule))
+                               match = true;
                }
        } else if (vinstances.IsObjectType<Dictionary>()) {
                if (rule.GetFVVar().IsEmpty())
@@ -128,16 +138,16 @@ bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const Appl
        
                Dictionary::Ptr dict = vinstances;
 
-               ObjectLock olock(dict);
-               BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
-                       frame.Locals->Set(rule.GetFKVar(), kv.first);
-                       frame.Locals->Set(rule.GetFVVar(), kv.second);
+               BOOST_FOREACH(const String& key, dict->GetKeys()) {
+                       frame.Locals->Set(rule.GetFKVar(), key);
+                       frame.Locals->Set(rule.GetFVVar(), dict->Get(key));
 
-                       EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule);
+                       if (EvaluateApplyRuleInstance(checkable, rule.GetName() + key, frame, rule))
+                               match = true;
                }
        }
 
-       return true;
+       return match;
 }
 
 void Notification::EvaluateApplyRules(const Host::Ptr& host)
index a56949d58477d260681ecef608094649e5e36229..5bafdaf85742a4557786eb112a754c54e442048b 100644 (file)
@@ -123,7 +123,7 @@ protected:
 private:
        void ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const CheckResult::Ptr& cr, bool force, const String& author = "", const String& text = "");
 
-       static void EvaluateApplyRuleInstance(const intrusive_ptr<Checkable>& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule);
+       static bool EvaluateApplyRuleInstance(const intrusive_ptr<Checkable>& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule);
        static bool EvaluateApplyRule(const intrusive_ptr<Checkable>& checkable, const ApplyRule& rule);
 };
 
index d9ef1c1f6c93e45850f038af8d6f114636dc300f..33336e8526efb6bcc8fb05480ef918fc5f1dbe3c 100644 (file)
@@ -40,8 +40,11 @@ void ScheduledDowntime::RegisterApplyRuleHandler(void)
        ApplyRule::RegisterType("ScheduledDowntime", targets);
 }
 
-void ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule)
+bool ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule)
 {
+       if (!rule.EvaluateFilter(frame))
+               return false;
+
        DebugInfo di = rule.GetDebugInfo();
 
        Log(LogDebug, "ScheduledDowntime")
@@ -70,6 +73,8 @@ void ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkabl
 
        ConfigItem::Ptr downtimeItem = builder->Compile();
        downtimeItem->Commit();
+
+       return true;
 }
 
 bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule)
@@ -91,27 +96,32 @@ bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const
        if (service)
                frame.Locals->Set("service", service);
 
-       if (!rule.EvaluateFilter(frame))
-               return false;
-
        Value vinstances;
 
        if (rule.GetFTerm()) {
-               vinstances = rule.GetFTerm()->Evaluate(frame);
+               try {
+                       vinstances = rule.GetFTerm()->Evaluate(frame);
+               } catch (const std::exception&) {
+                       /* Silently ignore errors here and assume there are no instances. */
+                       return false;
+               }
        } else {
                Array::Ptr instances = new Array();
                instances->Add("");
                vinstances = instances;
        }
 
+       bool match = false;
+
        if (vinstances.IsObjectType<Array>()) {
                if (!rule.GetFVVar().IsEmpty())
                        BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di));
 
                Array::Ptr arr = vinstances;
+               Array::Ptr arrclone = arr->ShallowClone();
 
-               ObjectLock olock(arr);
-               BOOST_FOREACH(const String& instance, arr) {
+               ObjectLock olock(arrclone);
+               BOOST_FOREACH(const String& instance, arrclone) {
                        String name = rule.GetName();
 
                        if (!rule.GetFKVar().IsEmpty()) {
@@ -119,7 +129,8 @@ bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const
                                name += instance;
                        }
 
-                       EvaluateApplyRuleInstance(checkable, name, frame, rule);
+                       if (EvaluateApplyRuleInstance(checkable, name, frame, rule))
+                               match = true;
                }
        } else if (vinstances.IsObjectType<Dictionary>()) {
                if (rule.GetFVVar().IsEmpty())
@@ -127,16 +138,16 @@ bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const
        
                Dictionary::Ptr dict = vinstances;
 
-               ObjectLock olock(dict);
-               BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
-                       frame.Locals->Set(rule.GetFKVar(), kv.first);
-                       frame.Locals->Set(rule.GetFVVar(), kv.second);
+               BOOST_FOREACH(const String& key, dict->GetKeys()) {
+                       frame.Locals->Set(rule.GetFKVar(), key);
+                       frame.Locals->Set(rule.GetFVVar(), dict->Get(key));
 
-                       EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule);
+                       if (EvaluateApplyRuleInstance(checkable, rule.GetName() + key, frame, rule))
+                               match = true;
                }
        }
 
-       return true;
+       return match;
 }
 
 void ScheduledDowntime::EvaluateApplyRules(const Host::Ptr& host)
index 723dfd7799bc336d23c2dd5e8f7fb59923ad277b..22394c5a42bb70a0e59be56cb26e6c2d7636a967 100644 (file)
@@ -63,7 +63,7 @@ private:
        std::pair<double, double> FindNextSegment(void);
        void CreateNextDowntime(void);
 
-       static void EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule);
+       static bool EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule);
        static bool EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule);
 };
 
index 4c9124e4b803655706f80be9adcac6e69c0945ed..5c39e9cf02a56edc15a9313f0ed2972fdd3c1be6 100644 (file)
@@ -39,8 +39,11 @@ void Service::RegisterApplyRuleHandler(void)
        ApplyRule::RegisterType("Service", targets);
 }
 
-void Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, ScriptFrame& frame, const ApplyRule& rule)
+bool Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, ScriptFrame& frame, const ApplyRule& rule)
 {
+       if (!rule.EvaluateFilter(frame))
+               return false;
+
        DebugInfo di = rule.GetDebugInfo();
 
        Log(LogDebug, "Service")
@@ -64,6 +67,8 @@ void Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& nam
 
        ConfigItem::Ptr serviceItem = builder->Compile();
        serviceItem->Commit();
+
+       return true;
 }
 
 bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule)
@@ -79,27 +84,32 @@ bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule)
                rule.GetScope()->CopyTo(frame.Locals);
        frame.Locals->Set("host", host);
 
-       if (!rule.EvaluateFilter(frame))
-               return false;
-
        Value vinstances;
 
        if (rule.GetFTerm()) {
-               vinstances = rule.GetFTerm()->Evaluate(frame);
+               try {
+                       vinstances = rule.GetFTerm()->Evaluate(frame);
+               } catch (const std::exception&) {
+                       /* Silently ignore errors here and assume there are no instances. */
+                       return false;
+               }
        } else {
                Array::Ptr instances = new Array();
                instances->Add("");
                vinstances = instances;
        }
 
+       bool match = false;
+
        if (vinstances.IsObjectType<Array>()) {
                if (!rule.GetFVVar().IsEmpty())
                        BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di));
 
                Array::Ptr arr = vinstances;
+               Array::Ptr arrclone = arr->ShallowClone();
 
-               ObjectLock olock(arr);
-               BOOST_FOREACH(const String& instance, arr) {
+               ObjectLock olock(arrclone);
+               BOOST_FOREACH(const String& instance, arrclone) {
                        String name = rule.GetName();
 
                        if (!rule.GetFKVar().IsEmpty()) {
@@ -107,7 +117,8 @@ bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule)
                                name += instance;
                        }
 
-                       EvaluateApplyRuleInstance(host, name, frame, rule);
+                       if (EvaluateApplyRuleInstance(host, name, frame, rule))
+                               match = true;
                }
        } else if (vinstances.IsObjectType<Dictionary>()) {
                if (rule.GetFVVar().IsEmpty())
@@ -115,16 +126,16 @@ bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule)
        
                Dictionary::Ptr dict = vinstances;
 
-               ObjectLock olock(dict);
-               BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
-                       frame.Locals->Set(rule.GetFKVar(), kv.first);
-                       frame.Locals->Set(rule.GetFVVar(), kv.second);
+               BOOST_FOREACH(const String& key, dict->GetKeys()) {
+                       frame.Locals->Set(rule.GetFKVar(), key);
+                       frame.Locals->Set(rule.GetFVVar(), dict->Get(key));
 
-                       EvaluateApplyRuleInstance(host, rule.GetName() + kv.first, frame, rule);
+                       if (EvaluateApplyRuleInstance(host, rule.GetName() + key, frame, rule))
+                               match = true;
                }
        }
 
-       return true;
+       return match;
 }
 
 void Service::EvaluateApplyRules(const Host::Ptr& host)
index 1c61fbfeb31708798ab86823919ec7516d2d1580..548b6474622ca9935050ce4cc6dbed4914757d1c 100644 (file)
@@ -61,7 +61,7 @@ protected:
 private:
        Host::Ptr m_Host;
 
-       static void EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, ScriptFrame& frame, const ApplyRule& rule);
+       static bool EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, ScriptFrame& frame, const ApplyRule& rule);
        static bool EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule);
 };