MINOR: mworker/cli: mcli-debug-mode enables every command
"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.
diff --git a/doc/management.txt b/doc/management.txt
index 89344dc..b9630c3 100644
--- a/doc/management.txt
+++ b/doc/management.txt
@@ -3674,15 +3674,24 @@
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 and "mcli-debug-mode" in 9.4.1.
- See also "experimental-mode" in Section 9.3.
+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
diff --git a/include/haproxy/cli-t.h b/include/haproxy/cli-t.h
index 3760789..4f5e358 100644
--- a/include/haproxy/cli-t.h
+++ b/include/haproxy/cli-t.h
@@ -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)
diff --git a/src/cli.c b/src/cli.c
index 2f5141d..cedf2f4 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -122,7 +122,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
{ { "_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 },