]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add a Lua maintenance hook
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 6 Feb 2024 14:44:35 +0000 (15:44 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 6 Feb 2024 14:50:21 +0000 (15:50 +0100)
Having a hook that can accept multiple callbacks makes it a lot easier
to manage the execution of several, independant tasks that needs to be
called regularly.

pdns/dnsdist-console.cc
pdns/dnsdist-lua.cc
pdns/dnsdist.cc
pdns/dnsdistdist/Makefile.am
pdns/dnsdistdist/dnsdist-lua-hooks.cc [new file with mode: 0644]
pdns/dnsdistdist/dnsdist-lua-hooks.hh [new file with mode: 0644]
pdns/dnsdistdist/docs/reference/config.rst
regression-tests.dnsdist/test_DNSCrypt.py

index 0f9e085735f9653fce618134a1a3cb870ec89de7..704db5d362314e9bc296b7034ca3be9b5f156130 100644 (file)
@@ -491,6 +491,7 @@ const std::vector<ConsoleKeyword> g_consoleKeywords{
   { "addLocal", true, R"(addr [, {doTCP=true, reusePort=false, tcpFastOpenQueueSize=0, interface="", cpus={}}])", "add `addr` to the list of addresses we listen on" },
   { "addCacheHitResponseAction", true, R"(DNS rule, DNS response action [, {uuid="UUID", name="name"}}])", "add a cache hit response rule" },
   { "addCacheInsertedResponseAction", true, R"(DNS rule, DNS response action [, {uuid="UUID", name="name"}}])", "add a cache inserted response rule" },
+  { "addMaintenanceCallback", true, "callback", "register a function to be called as part of the maintenance hook, every second" },
   { "addResponseAction", true, R"(DNS rule, DNS response action [, {uuid="UUID", name="name"}}])", "add a response rule" },
   { "addSelfAnsweredResponseAction", true, R"(DNS rule, DNS response action [, {uuid="UUID", name="name"}}])", "add a self-answered response rule" },
   { "addTLSLocal", true, "addr, certFile(s), keyFile(s) [,params]", "listen to incoming DNS over TLS queries on the specified address using the specified certificate (or list of) and key (or list of). The last parameter is a table" },
index 50112a3730b0f09d52cc19c7ab5258d80932105f..b241742675cf4fe7976c6fb69a53e04bd2e50cea 100644 (file)
@@ -46,6 +46,7 @@
 #include "dnsdist-ecs.hh"
 #include "dnsdist-healthchecks.hh"
 #include "dnsdist-lua.hh"
+#include "dnsdist-lua-hooks.hh"
 #include "xsk.hh"
 #ifdef LUAJIT_VERSION
 #include "dnsdist-lua-ffi.hh"
@@ -3405,6 +3406,7 @@ vector<std::function<void(void)>> setupLua(LuaContext& luaCtx, bool client, bool
   setupLuaBindingsPacketCache(luaCtx, client);
   setupLuaBindingsProtoBuf(luaCtx, client, configCheck);
   setupLuaBindingsRings(luaCtx, client);
+  dnsdist::lua::hooks::setupLuaHooks(luaCtx);
   setupLuaInspection(luaCtx);
   setupLuaRules(luaCtx);
   setupLuaVars(luaCtx);
index d83066e954b8c86b48621f49726be12bb1507d92..086765d1826734ad05463bc0916854f98acf6c01 100644 (file)
@@ -61,6 +61,7 @@
 #include "dnsdist-edns.hh"
 #include "dnsdist-healthchecks.hh"
 #include "dnsdist-lua.hh"
+#include "dnsdist-lua-hooks.hh"
 #include "dnsdist-nghttp2.hh"
 #include "dnsdist-proxy-protocol.hh"
 #include "dnsdist-random.hh"
@@ -2236,19 +2237,20 @@ static void maintThread()
 
     {
       auto lua = g_lua.lock();
-      auto f = lua->readVariable<boost::optional<std::function<void()> > >("maintenance");
-      if (f) {
-        try {
+      try {
+        auto f = lua->readVariable<boost::optional<std::function<void()> > >("maintenance");
+        if (f) {
           (*f)();
-          secondsToWaitLog = 0;
         }
-        catch (const std::exception &e) {
-          if (secondsToWaitLog <= 0) {
-            warnlog("Error during execution of maintenance function: %s", e.what());
-            secondsToWaitLog = 61;
-          }
-          secondsToWaitLog -= interval;
+        dnsdist::lua::hooks::runMaintenanceHook(*lua);
+        secondsToWaitLog = 0;
+      }
+      catch (const std::exception &e) {
+        if (secondsToWaitLog <= 0) {
+          warnlog("Error during execution of maintenance function(s): %s", e.what());
+          secondsToWaitLog = 61;
         }
+        secondsToWaitLog -= interval;
       }
     }
 
index 60e76e0ff81e3a387b2b17577e004a39b245f1ea..68ab167dcfbd9ba951713ec59e982191c8eb3c43 100644 (file)
@@ -178,6 +178,7 @@ dnsdist_SOURCES = \
        dnsdist-lua-bindings.cc \
        dnsdist-lua-ffi-interface.h dnsdist-lua-ffi-interface.inc \
        dnsdist-lua-ffi.cc dnsdist-lua-ffi.hh \
+       dnsdist-lua-hooks.cc dnsdist-lua-hooks.hh \
        dnsdist-lua-inspection-ffi.cc dnsdist-lua-inspection-ffi.h \
        dnsdist-lua-inspection.cc \
        dnsdist-lua-network.cc dnsdist-lua-network.hh \
diff --git a/pdns/dnsdistdist/dnsdist-lua-hooks.cc b/pdns/dnsdistdist/dnsdist-lua-hooks.cc
new file mode 100644 (file)
index 0000000..2b1814a
--- /dev/null
@@ -0,0 +1,32 @@
+
+#include "dnsdist-lua-hooks.hh"
+#include "dnsdist-lua.hh"
+#include "lock.hh"
+
+namespace dnsdist::lua::hooks
+{
+static LockGuarded<std::vector<MaintenanceCallback>> s_maintenanceHook;
+
+void runMaintenanceHook(const LuaContext& context)
+{
+  (void)context;
+  for (const auto& callback : *(s_maintenanceHook.lock())) {
+    callback();
+  }
+}
+
+void addMaintenanceCallback(const LuaContext& context, MaintenanceCallback callback)
+{
+  (void)context;
+  s_maintenanceHook.lock()->push_back(std::move(callback));
+}
+
+void setupLuaHooks(LuaContext& luaCtx)
+{
+  luaCtx.writeFunction("addMaintenanceCallback", [&luaCtx](const MaintenanceCallback& callback) {
+    setLuaSideEffect();
+    addMaintenanceCallback(luaCtx, callback);
+  });
+}
+
+}
diff --git a/pdns/dnsdistdist/dnsdist-lua-hooks.hh b/pdns/dnsdistdist/dnsdist-lua-hooks.hh
new file mode 100644 (file)
index 0000000..573ab95
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#pragma once
+
+#include <functional>
+
+class LuaContext;
+
+namespace dnsdist::lua::hooks
+{
+using MaintenanceCallback = std::function<void()>;
+void runMaintenanceHook(const LuaContext& context);
+void addMaintenanceCallback(MaintenanceCallback callback);
+void setupLuaHooks(LuaContext& luaCtx);
+}
index b3e2f5c2dbcaee7709d9d965e272515e420a5f5b..a252a5e15044ba457bb19b1d4265b1fcfaccac3f 100644 (file)
@@ -1982,6 +1982,23 @@ These values can be set at configuration time via:
 Other functions
 ---------------
 
+.. function:: addMaintenanceCallback(callback)
+
+  .. versionadded:: 1.10.0
+
+  Register a Lua function to be called as part of the ``maintenance`` hook, which is executed roughly every second.
+  The function should not block for a long period of time, as it would otherwise delay the execution of the other functions registered for this hook, as well as the execution of the :func:`maintenance` function.
+
+  :param function callback: The function to be called. It takes no parameter and returns no value.
+
+  .. code-block:: lua
+
+    function myCallback(hostname, ips)
+      print('called')
+    end
+    addMaintenanceCallback(myCallback)
+
+
 .. function:: getAddressInfo(hostname, callback)
 
   .. versionadded:: 1.9.0
@@ -2026,6 +2043,7 @@ Other functions
 
   If this function exists, it is called every second to do regular tasks.
   This can be used for e.g. :doc:`Dynamic Blocks <../guides/dynblocks>`.
+  See also :func:`addMaintenanceCallback`.
 
 .. function:: threadmessage(cmd, dict)
 
index 6f8df586ec3d7020828f2a657b6166bc294e0eff..c5e150e8d9b25dcc5b57e2d027c3e69647da6fd9 100644 (file)
@@ -332,7 +332,7 @@ class TestDNSCryptAutomaticRotation(DNSCryptTest):
 
     local last = 0
     serial = %d
-    function maintenance()
+    function reloadCallback()
       local now = os.time()
       if ((now - last) > 2) then
         serial = serial + 1
@@ -340,6 +340,7 @@ class TestDNSCryptAutomaticRotation(DNSCryptTest):
         last = now
       end
     end
+    addMaintenanceCallback(reloadCallback)
     """
 
     _config_params = ['_consoleKeyB64', '_consolePort', '_resolverCertificateSerial', '_resolverCertificateValidFrom', '_resolverCertificateValidUntil', '_dnsDistPortDNSCrypt', '_providerName', '_testServerPort', '_resolverCertificateSerial']