]> granicus.if.org Git - pdns/commitdiff
Improved Lua records - Added all and none selector, added defaultSelector on ifurlup()
authorOlivier Voortman <ov@taktik.com>
Wed, 29 Aug 2018 08:43:44 +0000 (10:43 +0200)
committerCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Thu, 29 Nov 2018 15:31:46 +0000 (16:31 +0100)
docs/lua-records/functions.rst
pdns/lua-record.cc

index af5e21c8cb3fc7cb89f439bd1bb305b64bdb8813..ae4afc47c6048d9e66c739ce3299123e86b22a30 100644 (file)
@@ -46,7 +46,7 @@ Record creation functions
 
   Various options can be set in the ``options`` parameter:
 
-  - ``selector``: used to pick the IP address from list of viable candidates. Choices include 'pickclosest', 'random', 'hashed'.
+  - ``selector``: used to pick the IP address from list of viable candidates. Choices include 'pickclosest', 'random', 'hashed', 'all', 'none'.
   - ``source``: Source IP address to check from
 
 
@@ -56,16 +56,14 @@ Record creation functions
   ``url``. In addition, multiple groups of IP addresses can be supplied. The
   first set with a working (available) IP address is used.
 
-  If all addresses are down, as usual, a random element from all sets is
-  returned.
-
   :param string url: The url to retrieve.
   :param addresses: List of lists of IP addresses to check the URL on.
   :param options: Table of options for this specific check, see below.
 
   Various options can be set in the ``options`` parameter:
 
-  - ``selector``: used to pick the IP address from list of viable candidates. Choices include 'pickclosest', 'random', 'hashed'.
+  - ``selector``: used to pick the IP address from list of viable candidates. Choices include 'pickclosest', 'random', 'hashed', 'all', 'none'.
+  - ``defaultSelector``: used to pick the IP address from list of all candidates if all addresses are down. Choices include 'pickclosest', 'random', 'hashed', 'all', 'none'.
   - ``source``: Source IP address to check from
   - ``stringmatch``: check ``url`` for this string, only declare 'up' if found
 
index 31a1cec52c56b90123a4f2b35a54a37b22958119..cc1dc0538a61172a445a6d1b27ad89039f23305b 100644 (file)
@@ -405,23 +405,44 @@ static std::vector<DNSZoneRecord> lookup(const DNSName& name, uint16_t qtype, in
   return ret;
 }
 
-static ComboAddress useSelector(const boost::optional<std::unordered_map<string, string>>& options, const ComboAddress& bestwho, const vector<ComboAddress>& candidates)
+static std::string getOptionValue(const boost::optional<std::unordered_map<string, string>>& options, const std::string &name, const std::string &defaultValue)
 {
-  string selector="random";
+  string selector=defaultValue;
   if(options) {
-    if(options->count("selector"))
-      selector=options->find("selector")->second;
+    if(options->count(name))
+      selector=options->find(name)->second;
   }
+  return selector;
+}
+
+static vector<ComboAddress> useSelector(const std::string &selector, const ComboAddress& bestwho, const vector<ComboAddress>& candidates)
+{
+  vector<ComboAddress> ret;
 
-  if(selector=="random")
-    return pickrandom(candidates);
+  if(selector=="none")
+    return ret;
+  else if(selector=="all")
+    return candidates;
+  else if(selector=="random")
+    ret.emplace_back(pickrandom(candidates));
   else if(selector=="pickclosest")
-    return pickclosest(bestwho, candidates);
+    ret.emplace_back(pickclosest(bestwho, candidates));
   else if(selector=="hashed")
-    return hashed(bestwho, candidates);
+    ret.emplace_back(hashed(bestwho, candidates));
+  else {
+    g_log<<Logger::Warning<<"LUA Record called with unknown selector '"<<selector<<"'"<<endl;
+    ret.emplace_back(pickrandom(candidates));
+  }
+
+  return ret;
+}
 
-  g_log<<Logger::Warning<<"LUA Record called with unknown selector '"<<selector<<"'"<<endl;
-  return pickrandom(candidates);
+static vector<string> convIpListToString(const vector<ComboAddress> &comboAddresses)
+{
+  vector<string> ret;
+  for (ComboAddress c : comboAddresses)
+    ret.emplace_back(c.toString());
+  return ret;
 }
 
 static vector<ComboAddress> convIplist(const iplist_t& src)
@@ -672,9 +693,9 @@ std::vector<shared_ptr<DNSRecordContent>> luaSynth(const std::string& code, cons
         // if no IP is available, use selector on the whole set
         candidates = std::move(unavailables);
       }
-      ComboAddress res=useSelector(options, bestwho, candidates);
 
-      return res.toString();
+      vector<ComboAddress> res = useSelector(getOptionValue(options, "selector", "random"), bestwho, candidates);
+      return convIpListToString(res);
     });
 
   lua.writeFunction("ifurlup", [&bestwho](const std::string& url,
@@ -704,20 +725,20 @@ std::vector<shared_ptr<DNSRecordContent>> luaSynth(const std::string& code, cons
           }
         }
         if(!available.empty()) {
-          ComboAddress res=useSelector(options, bestwho, available);
-
-          return res.toString();
+          vector<ComboAddress> res = useSelector(getOptionValue(options, "selector", "random"), bestwho, available);
+          return convIpListToString(res);
         }
       }
 
-      // All units down, return a single, random record
+      // All units down, apply defaultSelector on all candidates
       vector<ComboAddress> ret{};
       for(const auto& unit : candidates) {
         ret.insert(ret.end(), unit.begin(), unit.end());
       }
 
-      return pickrandom(ret).toString();
-                    });
+      vector<ComboAddress> res = useSelector(getOptionValue(options, "defaultSelector", "random"), bestwho, ret);
+      return convIpListToString(res);
+    });
 
 
   /* idea: we have policies on vectors of ComboAddresses, like