From: Aurélien Nephtali Date: Wed, 18 Apr 2018 12:04:47 +0000 (+0200) Subject: MINOR: map: Add payload support to "add map" X-Git-Tag: v1.9-dev1~286 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=25650ce5139ba5e8552930a1cc0c0c5c45e9e4d1;p=thirdparty%2Fhaproxy.git MINOR: map: Add payload support to "add map" It is now possible to use a payload with the "add map" command. These syntaxes will work the same way: # echo "add map #-1 key value" | socat /tmp/sock1 - # echo -e "add map #-1 <<\n$(cat data)\n" | socat /tmp/sock1 - with # cat data key1 value1 with spaces key2 value2 key3 value3 also with spaces Signed-off-by: Aurélien Nephtali --- diff --git a/doc/management.txt b/doc/management.txt index bca0fd469d..c0c3f48234 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -1331,11 +1331,28 @@ add acl In this case, you must use the command "add map" in place of "add acl". add map +add map Add an entry into the map to associate the value to the key . This command does not verify if the entry already exists. It is mainly used to fill a map after a clear operation. Note that if the reference is a file and is shared with a map, this map will contain also a new - pattern entry. + pattern entry. Using the payload syntax it is possible to add multiple + key/value pairs by entering them on separate lines. On each new line, the + first word is the key and the rest of the line is considered to be the value + which can even contains spaces. + + Example: + + # socat /tmp/sock1 - + prompt + + > add map #-1 << + + key1 value1 + + key2 value2 with spaces + + key3 value3 also with spaces + + key4 value4 + + > clear counters Clear the max values of the statistics counters in each proxy (frontend & diff --git a/src/map.c b/src/map.c index d02a0255c7..ad47c7f233 100644 --- a/src/map.c +++ b/src/map.c @@ -772,6 +772,20 @@ static int cli_parse_set_map(char **args, char *payload, struct appctx *appctx, return 1; } +static int map_add_key_value(struct appctx *appctx, const char *key, const char *value, char **err) +{ + int ret; + + HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock); + if (appctx->ctx.map.display_flags == PAT_REF_MAP) + ret = pat_ref_add(appctx->ctx.map.ref, key, value, err); + else + ret = pat_ref_add(appctx->ctx.map.ref, key, NULL, err); + HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock); + + return ret; +} + static int cli_parse_add_map(char **args, char *payload, struct appctx *appctx, void *private) { if (strcmp(args[1], "map") == 0 || @@ -785,13 +799,16 @@ static int cli_parse_add_map(char **args, char *payload, struct appctx *appctx, else appctx->ctx.map.display_flags = PAT_REF_ACL; - /* If the keywork is "map", we expect three parameters, if it - * is "acl", we expect only two parameters + /* If the keyword is "map", we expect: + * - three parameters if there is no payload + * - one parameter if there is a payload + * If it is "acl", we expect only two parameters */ if (appctx->ctx.map.display_flags == PAT_REF_MAP) { - if (!*args[2] || !*args[3] || !*args[4]) { + if ((!payload && (!*args[2] || !*args[3] || !*args[4])) || + (payload && !*args[2])) { appctx->ctx.cli.severity = LOG_ERR; - appctx->ctx.cli.msg = "'add map' expects three parameters: map identifier, key and value.\n"; + appctx->ctx.cli.msg = "'add map' expects three parameters (map identifier, key and value) or one parameter (map identifier) and a payload\n"; appctx->st0 = CLI_ST_PRINT; return 1; } @@ -832,26 +849,69 @@ static int cli_parse_add_map(char **args, char *payload, struct appctx *appctx, return 1; } - /* Add value. */ + /* Add value(s). */ err = NULL; - HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock); - if (appctx->ctx.map.display_flags == PAT_REF_MAP) - ret = pat_ref_add(appctx->ctx.map.ref, args[3], args[4], &err); - else - ret = pat_ref_add(appctx->ctx.map.ref, args[3], NULL, &err); - HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock); - if (!ret) { - if (err) { - memprintf(&err, "%s.\n", err); - appctx->ctx.cli.err = err; - appctx->st0 = CLI_ST_PRINT_FREE; + if (!payload) { + ret = map_add_key_value(appctx, args[3], args[4], &err); + if (!ret) { + if (err) { + memprintf(&err, "%s.\n", err); + appctx->ctx.cli.err = err; + appctx->st0 = CLI_ST_PRINT_FREE; + } + else { + appctx->ctx.cli.severity = LOG_ERR; + appctx->ctx.cli.msg = "Failed to add an entry.\n"; + appctx->st0 = CLI_ST_PRINT; + } + return 1; } - else { - appctx->ctx.cli.severity = LOG_ERR; - appctx->ctx.cli.msg = "Failed to add an entry.\n"; - appctx->st0 = CLI_ST_PRINT; + } + else { + const char *end = payload + strlen(payload); + + while (payload < end) { + char *key, *value; + size_t l; + + /* key */ + key = payload; + l = strcspn(key, " \t"); + payload += l; + + if (!*payload && appctx->ctx.map.display_flags == PAT_REF_MAP) { + memprintf(&err, "Missing value for key '%s'.\n", key); + appctx->ctx.cli.err = err; + appctx->st0 = CLI_ST_PRINT_FREE; + return 1; + } + key[l] = 0; + payload++; + + /* value */ + payload += strspn(payload, " \t"); + value = payload; + l = strcspn(value, "\n"); + payload += l; + if (*payload) + payload++; + value[l] = 0; + + ret = map_add_key_value(appctx, key, value, &err); + if (!ret) { + if (err) { + memprintf(&err, "%s.\n", err); + appctx->ctx.cli.err = err; + appctx->st0 = CLI_ST_PRINT_FREE; + } + else { + appctx->ctx.cli.severity = LOG_ERR; + appctx->ctx.cli.msg = "Failed to add a key.\n"; + appctx->st0 = CLI_ST_PRINT; + } + return 1; + } } - return 1; } /* The add is done, send message. */