List,

while working on updating my haproxy-auth-request [1] to make use of
haproxy-lua-http [2] instead of the crappy lua-socket [3] I realized
that it would be difficult for the administrator to use the script
afterwards.

The reason is that `require` in Lua attempts to search the modules
either in the current working directory (which is different from
the filename of the script executing the `require` and which most
likely is not anywhere near HAProxy's configuration folder) or within
Lua's library path which is compiled into Lua (in my case this is
something like `/usr/share/lua/5.3/`).

Add a `lua-prepend-path` configuration option that prepend the given
string to Lua's path, allowing scripts loaded with `lua-load` to find
libraries within that path.

Example configuration:

global
        lua-prepend-path /etc/haproxy/lua-modules/?/init.lua
        lua-prepend-path /etc/haproxy/lua-modules/?.lua
        lua-load /etc/haproxy/lua-modules/auth-request.lua

would result in something like this:

[ALERT] 007/225248 (6638) : parsing [./haproxy.cfg:5] : Lua runtime error: 
auth-request.lua:23: module 'haproxy-lua-http' not found:
        no field package.preload['haproxy-lua-http']
        no file '/etc/haproxy/lua-modules/haproxy-lua-http.lua'
        no file '/etc/haproxy/lua-modules/haproxy-lua-http/init.lua'
        no file '/usr/local/share/lua/5.3/haproxy-lua-http.lua'
        no file '/usr/local/share/lua/5.3/haproxy-lua-http/init.lua'
        no file '/usr/local/lib/lua/5.3/haproxy-lua-http.lua'
        no file '/usr/local/lib/lua/5.3/haproxy-lua-http/init.lua'
        no file '/usr/share/lua/5.3/haproxy-lua-http.lua'
        no file '/usr/share/lua/5.3/haproxy-lua-http/init.lua'
        no file './haproxy-lua-http.lua'
        no file './haproxy-lua-http/init.lua'
        no file '/usr/local/lib/lua/5.3/haproxy-lua-http.so'
        no file '/usr/lib/x86_64-linux-gnu/lua/5.3/haproxy-lua-http.so'
        no file '/usr/lib/lua/5.3/haproxy-lua-http.so'
        no file '/usr/local/lib/lua/5.3/loadall.so'
        no file './haproxy-lua-http.so'

I'd appreciate if we could backport this to 2.1. It should be fairly
self-contained.

Best regards
Tim Düsterhus

[1] https://github.com/TimWolla/haproxy-auth-request
[2] https://github.com/haproxytech/haproxy-lua-http
[3] https://github.com/TimWolla/haproxy-auth-request/issues/4

Apply with `git am --scissors` to automatically cut the commit message.

-- >8 --
Subject: [PATCH] MINOR: lua: Add lua-prepend-path configuration option

lua-prepend-path allows the administrator to specify a custom Lua library
path to load custom Lua modules that are useful within the context of HAProxy
without polluting the global Lua library folder.
---
 doc/configuration.txt |  6 ++++++
 src/hlua.c            | 16 ++++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/doc/configuration.txt b/doc/configuration.txt
index d0bb97415..47a4db344 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -603,6 +603,7 @@ The following keywords are supported in the "global" 
section :
    - log-tag
    - log-send-hostname
    - lua-load
+   - lua-prepend-path
    - mworker-max-reloads
    - nbproc
    - nbthread
@@ -1080,6 +1081,11 @@ lua-load <file>
   This global directive loads and executes a Lua file. This directive can be
   used multiple times.
 
+lua-prepend-path <string>
+  Prepends the given string followed by a semicolon to Lua's search path.
+
+  see: https://www.lua.org/pil/8.1.html
+
 master-worker [no-exit-on-failure]
   Master-worker mode. It is equivalent to the command line "-W" argument.
   This mode will launch a "master" which will monitor the "workers". Using
diff --git a/src/hlua.c b/src/hlua.c
index 37f786687..4f39755b3 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -7458,8 +7458,24 @@ static int hlua_load(char **args, int section_type, 
struct proxy *curpx,
        return 0;
 }
 
+static int hlua_prepend_path(char **args, int section_type, struct proxy 
*curpx,
+                             struct proxy *defpx, const char *file, int line,
+                             char **err)
+{
+       lua_getglobal(gL.T, "package"); /* push package            */
+       lua_pushstring(gL.T, args[1]);  /* push given path         */
+       lua_pushstring(gL.T, ";");      /* push semicolon          */
+       lua_getfield(gL.T, -3, "path"); /* push old path           */
+       lua_concat(gL.T, 3);            /* concatenate to new path */
+       lua_setfield(gL.T, -2, "path"); /* store new path          */
+       lua_pop(gL.T, 1);               /* pop package             */
+
+       return 0;
+}
+
 /* configuration keywords declaration */
 static struct cfg_kw_list cfg_kws = {{ },{
+       { CFG_GLOBAL, "lua-prepend-path",         hlua_prepend_path },
        { CFG_GLOBAL, "lua-load",                 hlua_load },
        { CFG_GLOBAL, "tune.lua.session-timeout", hlua_session_timeout },
        { CFG_GLOBAL, "tune.lua.task-timeout",    hlua_task_timeout },
-- 
2.24.1


Reply via email to