]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: hlua: Allow argument on lua-lod(-per-thread) directives
authorThierry Fournier <tfournier@arpalert.org>
Mon, 19 Sep 2022 07:04:16 +0000 (09:04 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 22 Sep 2022 13:24:29 +0000 (15:24 +0200)
Allow per-lua file argument which makes multiples configuration
easier to handle

This patch fixes issue #1609.

doc/configuration.txt
doc/lua-api/index.rst
src/hlua.c

index 6d8226a8226be571e56124d8193c1758449375f1..939f7c489dc1b0ab9b1a0a215584f11fc20d1ff9 100644 (file)
@@ -1795,7 +1795,7 @@ log-tag <string>
   Sometimes it can be useful to differentiate between multiple processes
   running on the same host. See also the per-proxy "log-tag" directive.
 
-lua-load <file>
+lua-load <file> [ <arg1> [ <arg2> [ ... ] ] ]
   This global directive loads and executes a Lua file in the shared context
   that is visible to all threads. Any variable set in such a context is visible
   from any thread. This is the easiest and recommended way to load Lua programs
@@ -1804,7 +1804,14 @@ lua-load <file>
   way will always see 0 in the "core.thread" variable. This directive can be
   used multiple times.
 
-lua-load-per-thread <file>
+  args are avalaible in the lua file using the code below in the body of the
+  file. Do not forget that Lua arrays start at index 1. A "local" variable
+  declared in a file is avalaible in the entire file and not avalaible on
+  other files.
+
+     local args = table.pack(...)
+
+lua-load-per-thread <file> [ <arg1> [ <arg2> [ ... ] ] ]
   This global directive loads and executes a Lua file into each started thread.
   Any global variable has a thread-local visibility so that each thread could
   see a different value. As such it is strongly recommended not to use global
@@ -1821,6 +1828,8 @@ lua-load-per-thread <file>
   case it will be equivalent to lua-load). This directive can be used multiple
   times.
 
+  See lua-load for usage of args.
+
 lua-prepend-path <string> [<type>]
   Prepends the given string followed by a semicolon to Lua's package.<type>
   variable.
index 515d8853bd5510638b1a3d8b825b025910ddc1a5..847ab521e9d719510657797a8abe75a94649947f 100644 (file)
@@ -116,6 +116,38 @@ On other terminal, you can test with telnet:
     #:~ telnet 127.0.0.1 10001
     hello world
 
+Usage of load parameters
+------------------------
+
+HAProxy lua-load(-per-thread) directives allow a list of paramaters after
+the lua file name. These parameters are accessible through an array of args
+using this code `local args = table.pack(...)` in the body of loaded file.
+
+Below, a new version of the hello world using load parameters
+
+HAProxy configuration file (`hello_world.conf`):
+
+::
+
+    global
+       lua-load hello_world.lua "this is not an hello world"
+
+    listen proxy
+       bind 127.0.0.1:10001
+       tcp-request inspect-delay 1s
+       tcp-request content use-service lua.hello_world
+
+HAProxy Lua file (`hello_world.lua`):
+
+.. code-block:: lua
+
+    local args = table.pack(...)
+
+    core.register_service("hello_world", "tcp", function(applet)
+       applet:send(args[1] .. "\n")
+    end)
+
+
 Core class
 ==========
 
index d3a73d50e88795375bbda0c25049d40dff80ac39..2fd710d3a55c155dc605776066511051077696ea 100644 (file)
@@ -145,7 +145,7 @@ static struct list referenced_functions = LIST_HEAD_INIT(referenced_functions);
 static int hlua_state_id;
 
 /* This is a NULL-terminated list of lua file which are referenced to load per thread */
-static char **per_thread_load = NULL;
+static char ***per_thread_load = NULL;
 
 lua_State *hlua_init_state(int thread_id);
 
@@ -11236,20 +11236,27 @@ static int hlua_parse_maxmem(char **args, int section_type, struct proxy *curpx,
  * We are in the configuration parsing process of HAProxy, this abort() is
  * tolerated.
  */
-static int hlua_load_state(char *filename, lua_State *L, char **err)
+static int hlua_load_state(char **args, lua_State *L, char **err)
 {
        int error;
+       int nargs;
 
        /* Just load and compile the file. */
-       error = luaL_loadfile(L, filename);
+       error = luaL_loadfile(L, args[0]);
        if (error) {
-               memprintf(err, "error in Lua file '%s': %s", filename, lua_tostring(L, -1));
+               memprintf(err, "error in Lua file '%s': %s", args[0], lua_tostring(L, -1));
                lua_pop(L, 1);
                return -1;
        }
 
+       /* Push args in the Lua stack, except the first one which is the filename */
+       for (nargs = 1; *(args[nargs]) != 0; nargs++) {
+               lua_pushstring(L, args[nargs]);
+       }
+       nargs--;
+
        /* If no syntax error where detected, execute the code. */
-       error = lua_pcall(L, 0, LUA_MULTRET, 0);
+       error = lua_pcall(L, nargs, LUA_MULTRET, 0);
        switch (error) {
        case LUA_OK:
                break;
@@ -11291,7 +11298,7 @@ static int hlua_load(char **args, int section_type, struct proxy *curpx,
        /* loading for global state */
        hlua_state_id = 0;
        ha_set_thread(NULL);
-       return hlua_load_state(args[1], hlua_states[0], err);
+       return hlua_load_state(&args[1], hlua_states[0], err);
 }
 
 static int hlua_load_per_thread(char **args, int section_type, struct proxy *curpx,
@@ -11299,6 +11306,7 @@ static int hlua_load_per_thread(char **args, int section_type, struct proxy *cur
                                 char **err)
 {
        int len;
+       int i;
 
        if (*(args[1]) == 0) {
                memprintf(err, "'%s' expects a file as parameter.", args[0]);
@@ -11323,19 +11331,32 @@ static int hlua_load_per_thread(char **args, int section_type, struct proxy *cur
                memprintf(err, "out of memory error");
                return -1;
        }
-
-       per_thread_load[len]     = strdup(args[1]);
        per_thread_load[len + 1] = NULL;
 
+       /* count args excepting the first, allocate array and copy args */
+       for (i = 0; *(args[i + 1]) != 0; i++);
+       per_thread_load[len] = calloc(i + 1, sizeof(per_thread_load[len]));
        if (per_thread_load[len] == NULL) {
                memprintf(err, "out of memory error");
                return -1;
        }
+       for (i = 1; *(args[i]) != 0; i++) {
+               per_thread_load[len][i - 1] = strdup(args[i]);
+               if (per_thread_load[len][i - 1] == NULL) {
+                       memprintf(err, "out of memory error");
+                       return -1;
+               }
+       }
+       per_thread_load[len][i - 1] = strdup("");
+       if (per_thread_load[len][i - 1]  == NULL) {
+               memprintf(err, "out of memory error");
+               return -1;
+       }
 
        /* loading for thread 1 only */
        hlua_state_id = 1;
        ha_set_thread(NULL);
-       return hlua_load_state(args[1], hlua_states[1], err);
+       return hlua_load_state(per_thread_load[len], hlua_states[1], err);
 }
 
 /* Prepend the given <path> followed by a semicolon to the `package.<type>` variable