From: Christopher Faulet Date: Tue, 20 Feb 2024 17:39:50 +0000 (+0100) Subject: BUG/MAJOR: cli: Restore non-interactive mode behavior with pipelined commands X-Git-Tag: v3.0-dev4~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d93ecc;p=thirdparty%2Fhaproxy.git BUG/MAJOR: cli: Restore non-interactive mode behavior with pipelined commands The issue was decribed in commit "BUG/MEDIUM: cli: Warn if pipelined commands are delimited by a \n". In non-interactive mode, it was possible to use a newline character as delimiter for pipelined commands. As a consequence, it was possible to stop commands processing on the middle. With the above commit, a warning is emitted to notify users. With this one, we restore the expected behavior, as documented in the management guide. Only the first line of commands is parsed. This commit will not be backported to avoid breaking changes on stable versions. This commit has of course some visible effects. All script using a newline character as delimiter to pipeline commands in non-interactive mode will stop working. Only the first command will be evaluated, all others will be ignored. Pipelined commands MUST now be separated by a semi-colon. But there is a more subtle and probably more annoying change. It is no longer possible to pipeline commands with a payload ! A command with a payload will always be the last one evaluated because it must be finished by a newline (eventually preceeded by a custom pattern). It is really annoying to introduce such breaking change. But, on the long term, it is mandatory. The 2.8 will be the last LST version supporting the old behavior (with some warning however). This will let 4 years to users to adapt their scripts. No backport needed. --- diff --git a/include/haproxy/cli-t.h b/include/haproxy/cli-t.h index 847b107d9b..630f81848d 100644 --- a/include/haproxy/cli-t.h +++ b/include/haproxy/cli-t.h @@ -45,7 +45,7 @@ #define APPCTX_CLI_ST1_PAYLOAD (1 << 1) #define APPCTX_CLI_ST1_NOLF (1 << 2) #define APPCTX_CLI_ST1_TIMED (1 << 3) -#define APPCTX_CLI_ST1_SHUT_EXPECTED (1 << 4) +#define APPCTX_CLI_ST1_LASTCMD (1 << 4) #define CLI_PREFIX_KW_NB 5 #define CLI_MAX_MATCHES 5 diff --git a/src/cli.c b/src/cli.c index 0044997efb..89a2227886 100644 --- a/src/cli.c +++ b/src/cli.c @@ -813,22 +813,6 @@ static int cli_parse_request(struct appctx *appctx) if (!**args) return 0; - if (appctx->st1 & APPCTX_CLI_ST1_SHUT_EXPECTED) { - /* The previous command line was finished by a \n in non-interactive mode. - * It should not be followed by another command line. In non-interactive mode, - * only one line should be processed. Because of a bug, it is not respected. - * So emit a warning, only once in the process life, to warn users their script - * must be updated. - */ - appctx->st1 &= ~APPCTX_CLI_ST1_SHUT_EXPECTED; - if (ONLY_ONCE()) { - ha_warning("Commands sent to the CLI were chained using a new line character while in non-interactive mode." - " This is not reliable, not officially supported and will not be supported anymore in future versions. " - "Please use ';' to delimit commands instead."); - } - } - - kw = cli_find_kw(args); if (!kw || (kw->level & ~appctx->cli_level & ACCESS_MASTER_ONLY) || @@ -927,7 +911,6 @@ static int cli_output_msg(struct appctx *appctx, const char *msg, int severity, static void cli_io_handler(struct appctx *appctx) { struct stconn *sc = appctx_sc(appctx); - struct channel *req = sc_oc(sc); struct channel *res = sc_ic(sc); struct bind_conf *bind_conf = strm_li(__sc_strm(sc))->bind_conf; int reql; @@ -1049,7 +1032,7 @@ static void cli_io_handler(struct appctx *appctx) appctx->st1 &= ~APPCTX_CLI_ST1_PAYLOAD; if (!(appctx->st1 & APPCTX_CLI_ST1_PROMPT) && lf) - appctx->st1 |= APPCTX_CLI_ST1_SHUT_EXPECTED; + appctx->st1 |= APPCTX_CLI_ST1_LASTCMD; } } } @@ -1089,7 +1072,7 @@ static void cli_io_handler(struct appctx *appctx) cli_parse_request(appctx); chunk_reset(appctx->chunk); if (!(appctx->st1 & APPCTX_CLI_ST1_PROMPT) && lf) - appctx->st1 |= APPCTX_CLI_ST1_SHUT_EXPECTED; + appctx->st1 |= APPCTX_CLI_ST1_LASTCMD; } } @@ -1216,11 +1199,11 @@ static void cli_io_handler(struct appctx *appctx) * allows pipelined requests to be sent in * non-interactive mode. */ - if (!(appctx->st1 & APPCTX_CLI_ST1_PROMPT) && !co_data(req) && (!(appctx->st1 & APPCTX_CLI_ST1_PAYLOAD))) { - se_fl_set(appctx->sedesc, SE_FL_EOI); - appctx->st0 = CLI_ST_END; - continue; - } + if ((appctx->st1 & (APPCTX_CLI_ST1_PROMPT|APPCTX_CLI_ST1_PAYLOAD|APPCTX_CLI_ST1_LASTCMD)) == APPCTX_CLI_ST1_LASTCMD) { + se_fl_set(appctx->sedesc, SE_FL_EOI); + appctx->st0 = CLI_ST_END; + continue; + } /* switch state back to GETREQ to read next requests */ applet_reset_svcctx(appctx);