]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: management: add some basic keyword dump infrastructure
authorWilly Tarreau <w@1wt.eu>
Tue, 8 Mar 2022 15:01:40 +0000 (16:01 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 29 Mar 2022 15:55:54 +0000 (17:55 +0200)
It's difficult from outside haproxy to detect the supported keywords
and syntax. Interestingly, many of our modern keywords are enumerated
since they're registered from constructors, so it's not very hard to
enumerate most of them.

This patch creates some basic infrastructure to support dumping existing
keywords from different classes on stdout. The format will differ depending
on the classes, but the idea is that the output could easily be passed to
a script that generates some simple syntax highlighting rules, completion
rules for editors, syntax checkers or config parsers.

The principle chosen here is that if "-dK" is passed on the command-line,
at the end of the parsing the registered keywords will be dumped for the
requested classes passed after "-dK". Special name "help" will show known
classes, while "all" will execute all of them. The reason for doing that
after the end of the config processor is that it will also enumerate
internally-generated keywords, Lua or even those loaded from external
code (e.g. if an add-on is loaded using LD_PRELOAD). A typical way to
call this with a valid config would be:

    ./haproxy -dKall -q -c -f /path/to/config

If there's no config available, feeding /dev/null will also do the job,
though it will not be able to detect dynamically created keywords, of
course.

This patch also updates the management doc.

For now nothing but the help is listed, various subsystems will follow
in subsequent patches.

doc/management.txt
include/haproxy/global-t.h
src/haproxy.c

index 2e1b87db961684fd3272b3085f3419bd4db3d604..15bf82ce4bc29e1ce5416bc508737e5df5bbee97 100644 (file)
@@ -214,6 +214,34 @@ list of options is :
     getaddrinfo() exist on various systems and cause anomalies that are
     difficult to troubleshoot.
 
+  -dK<class[,class]*> : dumps the list of registered keywords in each class.
+    The list of classes is available with "-dKhelp". All classes may be dumped
+    using "-dKall", otherwise a selection of those shown in the help can be
+    specified as a comma-delimited list. The output format will vary depending
+    on what class of keywords is being dumped (e.g. "cfg" will show the known
+    configuration keywords in a format ressembling the config file format while
+    "smp" will show sample fetch functions prefixed with a compatibility matrix
+    with each rule set). These may rarely be used as-is by humans but can be of
+    great help for external tools that try to detect the appearance of new
+    keywords at certain places to automatically update some documentation,
+    syntax highlighting files, configuration parsers, API etc. The output
+    format may evolve a bit over time so it is really recommended to use this
+    output mostly to detect differences with previous archives. Note that not
+    all keywords are listed because many keywords have existed long before the
+    different keyword registration subsystems were created, and they do not
+    appear there. However since new keywords are only added via the modern
+    mechanisms, it's reasonably safe to assume that this output may be used to
+    detect language additions with a good accuracy. The keywords are only
+    dumped after the configuration is fully parsed, so that even dynamically
+    created keywords can be dumped. A good way to dump and exit is to run a
+    silent config check on an existing configuration:
+
+       ./haproxy -dKall -q -c -f foo.cfg
+
+    If no configuration file is available, using "-f /dev/null" will work as
+    well to dump all default keywords, but then the return status will not be
+    zero since there will be no listener, and will have to be ignored.
+
   -dL : dumps the list of dynamic shared libraries that are loaded at the end
    of the config processing. This will generally also include deep dependencies
    such as anything loaded from Lua code for example, as well as the executable
index 44eed88f7287bb99977c19a280a7bc469762124b..e8ded61908adb39402db175ab04f4cb7c59e2bea 100644 (file)
@@ -41,6 +41,7 @@
 #define        MODE_CHECK_CONDITION    0x800    /* -cc mode */
 #define        MODE_STOPPING   0x1000  /* the process is in the deinit phase, the event loop is not running anymore. */
 #define        MODE_DUMP_LIBS  0x2000  /* dump loaded libraries at the end of init phase */
+#define        MODE_DUMP_KWD   0x4000  /* dump registered keywords (see kwd_dump for the list) */
 
 /* list of last checks to perform, depending on config options */
 #define LSTCHK_CAP_BIND        0x00000001      /* check that we can bind to any port */
index 0da19ccdf6e2508c7883098df7cbce934e9f04cb..a037611e6631459cae248a7d3fbea2ce5d5c0dba 100644 (file)
@@ -242,6 +242,7 @@ const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
 
 char hostname[MAX_HOSTNAME_LEN];
 char *localpeer = NULL;
+static char *kwd_dump = NULL; // list of keyword dumps to produce
 
 static char **old_argv = NULL; /* previous argv but cleaned up */
 
@@ -603,6 +604,7 @@ static void usage(char *name)
 #if defined(HA_HAVE_DUMP_LIBS)
                "        -dL dumps loaded object files after config checks\n"
 #endif
+               "        -dK{class[,...]} dump registered keywords (use 'help' for list)\n"
                "        -dr ignores server address resolution failures\n"
                "        -dV disables SSL verify on servers side\n"
                "        -dW fails if any warning is emitted\n"
@@ -1656,6 +1658,10 @@ static void init_args(int argc, char **argv)
                        else if (*flag == 'd' && flag[1] == 'L')
                                arg_mode |= MODE_DUMP_LIBS;
 #endif
+                       else if (*flag == 'd' && flag[1] == 'K') {
+                               arg_mode |= MODE_DUMP_KWD;
+                               kwd_dump = flag + 2;
+                       }
                        else if (*flag == 'd')
                                arg_mode |= MODE_DEBUG;
                        else if (*flag == 'c' && flag[1] == 'c') {
@@ -1803,6 +1809,30 @@ static void init_args(int argc, char **argv)
        free(err_msg);
 }
 
+/* call the various keyword dump functions based on the comma-delimited list of
+ * classes in kwd_dump.
+ */
+static void dump_registered_keywords(void)
+{
+       char *end;
+       int all __maybe_unused = 0;
+
+       for (; kwd_dump && *kwd_dump; kwd_dump = end) {
+               end = strchr(kwd_dump, ',');
+               if (end)
+                       *(end++) = 0;
+
+               if (strcmp(kwd_dump, "help") == 0) {
+                       printf("# List of supported keyword classes:\n");
+                       printf("all: list all keywords\n");
+                       continue;
+               }
+               else if (strcmp(kwd_dump, "all") == 0) {
+                       all = 1;
+               }
+       }
+}
+
 /*
  * This function initializes all the necessary variables. It only returns
  * if everything is OK. If something fails, it exits.
@@ -1829,7 +1859,7 @@ static void init(int argc, char **argv)
 
        global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
                                    | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
-                                   | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS));
+                                   | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS | MODE_DUMP_KWD));
 
        if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
                unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
@@ -2096,6 +2126,9 @@ static void init(int argc, char **argv)
        }
 #endif
 
+       if (global.mode & MODE_DUMP_KWD)
+               dump_registered_keywords();
+
        if (global.mode & MODE_CHECK) {
                struct peers *pr;
                struct proxy *px;