]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MAJOR: cli: Restore non-interactive mode behavior with pipelined commands
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 20 Feb 2024 17:39:50 +0000 (18:39 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 23 Feb 2024 14:19:49 +0000 (15:19 +0100)
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.

include/haproxy/cli-t.h
src/cli.c

index 847b107d9b6f12554d0b82ffb00db5ee24965d93..630f81848d8d11783df2511bd8a1c7f6c99c080f 100644 (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
index 0044997efbc32d63caf9f6e97cc21dce3f2f1c17..89a22278864ee410690b710b1ac3ba7852174c30 100644 (file)
--- 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);