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.
This commit is contained in:
Christopher Faulet 2024-02-20 18:39:50 +01:00
parent 598c7f164c
commit 3d93ecc132
2 changed files with 8 additions and 25 deletions

View File

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

View File

@ -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,7 +1199,7 @@ 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))) {
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;