]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: cli: Report location of errors or any extra data for "show table"
authorAdis Nezirovic <anezirovic@haproxy.com>
Wed, 22 Jan 2020 15:50:27 +0000 (16:50 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 23 Jan 2020 09:43:52 +0000 (10:43 +0100)
When using multiple filters with "show table", it can be useful to
report which filter entry failed

  > show table MY_TABLE data.gpc0 gt 0 data.gpc0a lt 1000
  Filter entry #2: Unknown data type

  > show table MY_TABLE data.gpc0 gt 0 data.gpc0 lt 1000a
  Filter entry #2: Require a valid integer value to compare against

We now also catch garbage data after the filter

  > show table MY_TABLE data.gpc0 gt 0 data.gpc0 lt 1000 data.gpc0 gt 1\
    data.gpc0 gt 10 a
  Detected extra data in filter, 16th word of input, after '10'

Even before multi-filter feature we've also silently accepted garbage
after the input, hiding potential bugs

  > show table MY_TABLE data.gpc0 gt 0 data.gpc0
or
  > show table MY_TABLE data.gpc0 gt 0 a

In both cases, only first filter entry would be used, silently ignoring
extra filter entry or garbage data.

Last, but not the least, it is now possible to detect multi-filter
feature from cli with something like the following:

  > show table MY_TABLE data.blah
  Filter entry #1: Unknown data type

src/stick_table.c

index 1b397e59e4f8c4f1f47330e91059ca52c30eb5ad..1e7d4f3a865d50806bef1d5bf5f4fef54a372979 100644 (file)
@@ -3601,6 +3601,7 @@ static int table_process_entry_per_key(struct appctx *appctx, char **args)
 static int table_prepare_data_request(struct appctx *appctx, char **args)
 {
        int i;
+       char *err = NULL;
 
        if (appctx->ctx.table.action != STK_CLI_ACT_SHOW && appctx->ctx.table.action != STK_CLI_ACT_CLR)
                return cli_err(appctx, "content-based lookup is only supported with the \"show\" and \"clear\" actions\n");
@@ -3611,17 +3612,21 @@ static int table_prepare_data_request(struct appctx *appctx, char **args)
                /* condition on stored data value */
                appctx->ctx.table.data_type[i] = stktable_get_data_type(args[3+3*i] + 5);
                if (appctx->ctx.table.data_type[i] < 0)
-                       return cli_err(appctx, "Unknown data type\n");
+                       return cli_dynerr(appctx, memprintf(&err, "Filter entry #%i: Unknown data type\n", i + 1));
 
                if (!((struct stktable *)appctx->ctx.table.target)->data_ofs[appctx->ctx.table.data_type[i]])
-                       return cli_err(appctx, "Data type not stored in this table\n");
+                       return cli_dynerr(appctx, memprintf(&err, "Filter entry #%i: Data type not stored in this table\n", i + 1));
 
                appctx->ctx.table.data_op[i] = get_std_op(args[4+3*i]);
                if (appctx->ctx.table.data_op[i] < 0)
-                       return cli_err(appctx, "Require and operator among \"eq\", \"ne\", \"le\", \"ge\", \"lt\", \"gt\"\n");
+                       return cli_dynerr(appctx, memprintf(&err, "Filter entry #%i: Require and operator among \"eq\", \"ne\", \"le\", \"ge\", \"lt\", \"gt\"\n", i + 1));
 
                if (!*args[5+3*i] || strl2llrc(args[5+3*i], strlen(args[5+3*i]), &appctx->ctx.table.value[i]) != 0)
-                       return cli_err(appctx, "Require a valid integer value to compare against\n");
+                       return cli_dynerr(appctx, memprintf(&err, "Filter entry #%i: Require a valid integer value to compare against\n", i + 1));
+       }
+
+       if (*args[3+3*i]) {
+               return cli_dynerr(appctx, memprintf(&err, "Detected extra data in filter, %ith word of input, after '%s'\n", 3+3*i + 1, args[2+3*i]));
        }
 
        /* OK we're done, all the fields are set */