]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mworker/cli: mcli-debug-mode enables every command
authorWilliam Lallemand <wlallemand@haproxy.org>
Wed, 2 Feb 2022 10:43:20 +0000 (11:43 +0100)
committerWilliam Lallemand <wlallemand@haproxy.org>
Wed, 2 Feb 2022 14:51:24 +0000 (15:51 +0100)
"mcli-debug-mode on" enables every command that were meant for a worker,
on the CLI of the master. Which mean you can issue, "show fd", show
stat" in order to debug the MASTER proxy.

You can also combine it with "expert-mode on" or "experimental-mode on"
to access to more commands.

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

index 89344dc18346907dcc2e92eaa621b30c559e55ca..b9630c379b2897ce8fdbfaa94be4555b334ce731 100644 (file)
@@ -3674,15 +3674,24 @@ Example:
 
 expert-mode [on|off]
   This command activates the "expert-mode" for every worker accessed from the
-  master CLI.
+  master CLI. Combined with "mcli-debug-mode" it also activates the command on
+  the master.
 
-  See also "expert-mode" in Section 9.3.
+  See also "expert-mode" in Section 9.3 and "mcli-debug-mode" in 9.4.1.
 
 experimental-mode [on|off]
   This command activates the "experimental-mode" for every worker accessed from
-  the master CLI.
+  the master CLI. Combined with "mcli-debug-mode" it also activates the command on
+  the master.
 
-  See also "experimental-mode" in Section 9.3.
+  See also "experimental-mode" in Section 9.3 and "mcli-debug-mode" in 9.4.1.
+
+mcli-debug-mode [on|off]
+  This keyword allows a special mode in the master CLI which enables every
+  keywords that were meant for a worker CLI on the master CLI, allowing to debug
+  the master process. Once activated, you list the new available keywords with
+  "help". Combined with "experimental-mode" or "expert-mode" it enables even
+  more keywords.
 
 prompt
   When the prompt is enabled (via the "prompt" command), the context the CLI is
index 3760789d1307dd83a4568da4424dde33cd867fed..4f5e358de6f514f29a641672ba872f4bad432d39 100644 (file)
@@ -36,6 +36,7 @@
 #define ACCESS_MASTER_ONLY  0x0010  /* only works with the master */
 #define ACCESS_EXPERT       0x0020  /* access to dangerous commands reserved to experts */
 #define ACCESS_EXPERIMENTAL 0x0040
+#define ACCESS_MCLI_DEBUG   0x0080 /* allow the master CLI to use any command without the flag ACCESS_MASTER */
 
 /* flags for appctx->st1 */
 #define APPCTX_CLI_ST1_PROMPT  (1 << 0)
index 2f5141d5decabdf57ff011e737e92a862d1d9f26..cedf2f4aa76eca423133691aa4a0fc425cf24278 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -122,7 +122,8 @@ static char *cli_gen_usage_msg(struct appctx *appctx, char * const *args)
                for (kw = &kw_list->kw[0]; kw->str_kw[0]; kw++) {
                        if (kw->level & ~appctx->cli_level & (ACCESS_MASTER_ONLY|ACCESS_EXPERT|ACCESS_EXPERIMENTAL))
                                continue;
-                       if ((appctx->cli_level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) ==
+                       if (!(appctx->cli_level & ACCESS_MCLI_DEBUG) &&
+                           (appctx->cli_level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) ==
                            (ACCESS_MASTER_ONLY|ACCESS_MASTER))
                                continue;
 
@@ -162,8 +163,9 @@ static char *cli_gen_usage_msg(struct appctx *appctx, char * const *args)
                        for (kw = &kw_list->kw[0]; kw->str_kw[0]; kw++) {
                                if (kw->level & ~appctx->cli_level & (ACCESS_MASTER_ONLY|ACCESS_EXPERT|ACCESS_EXPERIMENTAL))
                                        continue;
-                               if ((appctx->cli_level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) ==
-                                   (ACCESS_MASTER_ONLY|ACCESS_MASTER))
+                               if (!(appctx->cli_level & ACCESS_MCLI_DEBUG) &&
+                                   ((appctx->cli_level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) ==
+                                   (ACCESS_MASTER_ONLY|ACCESS_MASTER)))
                                        continue;
 
                                for (idx = 0; idx < length; idx++) {
@@ -249,11 +251,13 @@ static char *cli_gen_usage_msg(struct appctx *appctx, char * const *args)
                        if (kw->level & ~appctx->cli_level & (ACCESS_MASTER_ONLY|ACCESS_EXPERT|ACCESS_EXPERIMENTAL))
                                continue;
 
-                       /* in master don't display commands that have neither the master bit
-                        * nor the master-only bit.
+                       /* in master, if the CLI don't have the
+                        * ACCESS_MCLI_DEBUG don't display commands that have
+                        * neither the master bit nor the master-only bit.
                         */
-                       if ((appctx->cli_level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) ==
-                           (ACCESS_MASTER_ONLY|ACCESS_MASTER))
+                       if (!(appctx->cli_level & ACCESS_MCLI_DEBUG) &&
+                           ((appctx->cli_level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) ==
+                           (ACCESS_MASTER_ONLY|ACCESS_MASTER)))
                                continue;
 
                        for (idx = 0; idx < length; idx++) {
@@ -750,7 +754,8 @@ static int cli_parse_request(struct appctx *appctx)
        kw = cli_find_kw(args);
        if (!kw ||
            (kw->level & ~appctx->cli_level & ACCESS_MASTER_ONLY) ||
-           (appctx->cli_level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) == (ACCESS_MASTER_ONLY|ACCESS_MASTER)) {
+           (!(appctx->cli_level & ACCESS_MCLI_DEBUG) &&
+            (appctx->cli_level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) == (ACCESS_MASTER_ONLY|ACCESS_MASTER))) {
                /* keyword not found in this mode */
                cli_gen_usage_msg(appctx, args);
                return 0;
@@ -1766,6 +1771,10 @@ static int cli_parse_expert_experimental_mode(char **args, char *payload, struct
                level = ACCESS_EXPERIMENTAL;
                level_str = "experimental-mode";
        }
+       else if (strcmp(args[0], "mcli-debug-mode") == 0) {
+               level = ACCESS_MCLI_DEBUG;
+               level_str = "mcli-debug-mode";
+       }
        else {
                return 1;
        }
@@ -2287,6 +2296,15 @@ int pcli_find_and_exec_kw(struct stream *s, char **args, int argl, char **errmsg
                if ((argl > 1) && (strcmp(args[1], "on") == 0))
                        s->pcli_flags |= ACCESS_EXPERIMENTAL;
                return argl;
+       } else if (strcmp(args[0], "mcli-debug-mode") == 0) {
+               if (!pcli_has_level(s, ACCESS_LVL_ADMIN)) {
+                       memprintf(errmsg, "Permission denied!\n");
+                       return -1;
+               }
+               s->pcli_flags &= ~ACCESS_MCLI_DEBUG;
+               if ((argl > 1) && (strcmp(args[1], "on") == 0))
+                       s->pcli_flags |= ACCESS_MCLI_DEBUG;
+               return argl;
        }
 
        return 0;
@@ -2435,6 +2453,12 @@ int pcli_parse_request(struct stream *s, struct channel *req, char **errmsg, int
        }
 
        if (ret > 1) {
+
+               /* the mcli-debug-mode is only sent to the applet of the master */
+               if ((s->pcli_flags & ACCESS_MCLI_DEBUG) && *next_pid <= 0) {
+                       ci_insert_line2(req, 0, "mcli-debug-mode on -", strlen("mcli-debug-mode on -"));
+                       ret += strlen("mcli-debug-mode on -") + 2;
+               }
                if (s->pcli_flags & ACCESS_EXPERIMENTAL) {
                        ci_insert_line2(req, 0, "experimental-mode on -", strlen("experimental-mode on -"));
                        ret += strlen("experimental-mode on -") + 2;
@@ -3049,6 +3073,7 @@ static struct cli_kw_list cli_kws = {{ },{
        { { "_getsocks", NULL },                 NULL,                                                                                                _getsocks, NULL },
        { { "expert-mode", NULL },               NULL,                                                                                                cli_parse_expert_experimental_mode, NULL, NULL, NULL, ACCESS_MASTER }, // not listed
        { { "experimental-mode", NULL },         NULL,                                                                                                cli_parse_expert_experimental_mode, NULL, NULL, NULL, ACCESS_MASTER }, // not listed
+       { { "mcli-debug-mode", NULL },         NULL,                                                                                                  cli_parse_expert_experimental_mode, NULL, NULL, NULL, ACCESS_MASTER_ONLY }, // not listed
        { { "set", "maxconn", "global",  NULL }, "set maxconn global <value>              : change the per-process maxconn setting",                  cli_parse_set_maxconn_global, NULL },
        { { "set", "rate-limit", NULL },         "set rate-limit <setting> <value>        : change a rate limiting value",                            cli_parse_set_ratelimit, NULL },
        { { "set", "severity-output",  NULL },   "set severity-output [none|number|string]: set presence of severity level in feedback information",  cli_parse_set_severity_output, NULL, NULL },