diff --git a/doc/management.txt b/doc/management.txt index ca5d858d0..5f88a5d71 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -1677,11 +1677,21 @@ enable server / This command is restricted and can only be issued on sockets configured for level "admin". +experimental-mode [on|off] + Without options, this indicates whether the experimental mode is enabled or + disabled on the current connection. When passed "on", it turns the + experimental mode on for the current CLI connection only. With "off" it turns + it off. + + The experimental mode is used to access to extra features still in + development. These features are currently not stable and should be used with + care. They may be subject to breaking changes accross versions. + expert-mode [on|off] - Without options, this indicates whether the expert mode is enabled or - disabled on the current connection. When passed "on", it turns the expert - mode on for the current CLI connection only. With "off" it turns it off. The - expert mode enables displaying of expert commands that can be extremely + This command is similar to experimental-mode but is used to toggle the + expert mode. + + The expert mode enables displaying of expert commands that can be extremely dangerous for the process and which may occasionally help developers collect important information about complex bugs. Any misuse of these features will likely lead to a process crash. Do not use this option without being invited @@ -1984,11 +1994,13 @@ show cli level operator Decrease the CLI level of the current CLI session to operator. It can't be - increased. It also drops expert mode. See also "show cli level". + increased. It also drops expert and experimental mode. See also "show cli + level". user Decrease the CLI level of the current CLI session to user. It can't be - increased. It also drops expert mode. See also "show cli level". + increased. It also drops expert and experimental mode. See also "show cli + level". show activity Reports some counters about internal events that will help developers and diff --git a/include/haproxy/cli-t.h b/include/haproxy/cli-t.h index 450781ab5..3d52f27b4 100644 --- a/include/haproxy/cli-t.h +++ b/include/haproxy/cli-t.h @@ -35,6 +35,7 @@ #define ACCESS_MASTER 0x0008 /* works with the master (and every other processes) */ #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 /* flags for appctx->st1 */ #define APPCTX_CLI_ST1_PROMPT (1 << 0) diff --git a/src/cli.c b/src/cli.c index 9aede1309..2e4da522f 100644 --- a/src/cli.c +++ b/src/cli.c @@ -103,7 +103,7 @@ static char *cli_gen_usage_msg(struct appctx *appctx, char * const *args) /* first, let's measure the longest match */ list_for_each_entry(kw_list, &cli_keywords.list, list) { for (kw = &kw_list->kw[0]; kw->str_kw[0]; kw++) { - if (kw->level & ~appctx->cli_level & (ACCESS_MASTER_ONLY|ACCESS_EXPERT)) + 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)) @@ -143,7 +143,7 @@ static char *cli_gen_usage_msg(struct appctx *appctx, char * const *args) if (args && args[length] && *args[length]) { list_for_each_entry(kw_list, &cli_keywords.list, list) { for (kw = &kw_list->kw[0]; kw->str_kw[0]; kw++) { - if (kw->level & ~appctx->cli_level & (ACCESS_MASTER_ONLY|ACCESS_EXPERT)) + 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)) @@ -226,9 +226,9 @@ static char *cli_gen_usage_msg(struct appctx *appctx, char * const *args) for (kw = &kw_list->kw[0]; kw->str_kw[0]; kw++) { /* in a worker or normal process, don't display master-only commands - * nor expert mode commands if not in this mode. + * nor expert/experimental mode commands if not in this mode. */ - if (kw->level & ~appctx->cli_level & (ACCESS_MASTER_ONLY|ACCESS_EXPERT)) + 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 @@ -730,6 +730,11 @@ static int cli_parse_request(struct appctx *appctx) return 0; } + if (kw->level & ~appctx->cli_level & ACCESS_EXPERIMENTAL) { + cli_err(appctx, "This command is restricted to experimental mode only.\n"); + return 0; + } + appctx->io_handler = kw->io_handler; appctx->io_release = kw->io_release; @@ -1677,29 +1682,45 @@ static int cli_parse_set_lvl(char **args, char *payload, struct appctx *appctx, appctx->cli_level &= ~ACCESS_LVL_MASK; appctx->cli_level |= ACCESS_LVL_USER; } - appctx->cli_level &= ~ACCESS_EXPERT; + appctx->cli_level &= ~(ACCESS_EXPERT|ACCESS_EXPERIMENTAL); return 1; } -/* parse and set the CLI expert-mode dynamically */ -static int cli_parse_expert_mode(char **args, char *payload, struct appctx *appctx, void *private) +/* parse and set the CLI expert/experimental-mode dynamically */ +static int cli_parse_expert_experimental_mode(char **args, char *payload, struct appctx *appctx, void *private) { + int level; + char *level_str; + char *output = NULL; + if (!cli_has_level(appctx, ACCESS_LVL_ADMIN)) return 1; - if (!*args[1]) - return (appctx->cli_level & ACCESS_EXPERT) - ? cli_msg(appctx, LOG_INFO, "expert-mode is ON\n") - : cli_msg(appctx, LOG_INFO, "expert-mode is OFF\n"); + if (!strcmp(args[0], "expert-mode")) { + level = ACCESS_EXPERT; + level_str = "expert-mode"; + } + else if (!strcmp(args[0], "experimental-mode")) { + level = ACCESS_EXPERIMENTAL; + level_str = "experimental-mode"; + } + else { + return 1; + } - appctx->cli_level &= ~ACCESS_EXPERT; + if (!*args[1]) { + memprintf(&output, "%s is %s\n", level_str, + (appctx->cli_level & level) ? "ON" : "OFF"); + return cli_dynmsg(appctx, LOG_INFO, output); + } + + appctx->cli_level &= ~level; if (strcmp(args[1], "on") == 0) - appctx->cli_level |= ACCESS_EXPERT; + appctx->cli_level |= level; return 1; } - int cli_parse_default(char **args, char *payload, struct appctx *appctx, void *private) { return 0; @@ -2928,7 +2949,8 @@ static struct cli_kw_list cli_kws = {{ },{ { { "operator", NULL }, "operator : lower the level of the current CLI session to operator", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER}, { { "user", NULL }, "user : lower the level of the current CLI session to user", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER}, { { "_getsocks", NULL }, NULL, _getsocks, NULL }, - { { "expert-mode", NULL }, NULL, cli_parse_expert_mode, NULL }, // not listed + { { "expert-mode", NULL }, NULL, cli_parse_expert_experimental_mode, NULL }, // not listed + { { "experimental-mode", NULL }, NULL, cli_parse_expert_experimental_mode, NULL }, // not listed {{},} }};