MINOR: cli: implement experimental-mode

Experimental mode is similar to expert-mode. It can be used to access to
features still in development.
This commit is contained in:
Amaury Denoyelle 2021-03-18 15:32:53 +01:00
parent 5ba8335186
commit 18487fb532
3 changed files with 56 additions and 21 deletions

View File

@ -1677,11 +1677,21 @@ enable server <backend>/<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

View File

@ -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)

View File

@ -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
{{},}
}};