MINOR: map/acl: add the "prepare map/acl" CLI command

This command allocates a new version for the map/acl, that will be usable
later to prepare the addition of new values to atomically replace existing
ones. Technically speaking the operation consists in atomically incrementing
the next version. There's no "undo" operation here, if a version is not
committed, it will automatically be trashed when committing a newer version.
This commit is contained in:
Willy Tarreau 2021-04-30 14:57:03 +02:00
parent ff3feeb5cf
commit 97218ce3a9
2 changed files with 56 additions and 0 deletions

View File

@ -1806,6 +1806,30 @@ new ssl cert <filename>
added to a directory or a crt-list. This command should be used in
combination with "set ssl cert" and "add ssl crt-list".
prepare acl <acl>
Allocate a new version number in ACL <acl> for atomic replacement. <acl> is
the #<id> or the <file> returned by "show acl". The new version number is
shown in response after "New version created:". This number will then be
usable to prepare additions of new entries into the ACL which will then
atomically replace the current ones once committed. It is reported as
"next_ver" in "show acl". There is no impact of allocating new versions, as
unused versions will automatically be removed once a more recent version is
committed. Version numbers are unsigned 32-bit values which wrap at the end,
so care must be taken when comparing them in an external program. This
command cannot be used if the reference <acl> is a file also used as a map.
In this case, the "prepare map" command must be used instead.
prepare map <map>
Allocate a new version number in map <map> for atomic replacement. <map> is
the #<id> or the <file> returned by "show map". The new version number is
shown in response after "New version created:". This number will then be
usable to prepare additions of new entries into the map which will then
atomically replace the current ones once committed. It is reported as
"next_ver" in "show map". There is no impact of allocating new versions, as
unused versions will automatically be removed once a more recent version is
committed. Version numbers are unsigned 32-bit values which wrap at the end,
so care must be taken when comparing them in an external program.
prompt
Toggle the prompt at the beginning of the line and enter or leave interactive
mode. In interactive mode, the connection is not closed after a command

View File

@ -11,6 +11,7 @@
*/
#include <stdio.h>
#include <syslog.h>
#include <haproxy/api.h>
#include <haproxy/applet-t.h>
@ -631,6 +632,35 @@ static int cli_parse_get_map(char **args, char *payload, struct appctx *appctx,
return 1;
}
static int cli_parse_prepare_map(char **args, char *payload, struct appctx *appctx, void *private)
{
if (strcmp(args[1], "map") == 0 ||
strcmp(args[1], "acl") == 0) {
uint next_gen;
char *msg = NULL;
/* Set ACL or MAP flags. */
if (args[1][0] == 'm')
appctx->ctx.map.display_flags = PAT_REF_MAP;
else
appctx->ctx.map.display_flags = PAT_REF_ACL;
/* lookup into the refs and check the map flag */
appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
if (!appctx->ctx.map.ref ||
!(appctx->ctx.map.ref->flags & appctx->ctx.map.display_flags)) {
if (appctx->ctx.map.display_flags == PAT_REF_MAP)
return cli_err(appctx, "Unknown map identifier. Please use #<id> or <file>.\n");
else
return cli_err(appctx, "Unknown ACL identifier. Please use #<id> or <file>.\n");
}
next_gen = pat_ref_newgen(appctx->ctx.map.ref);
return cli_dynmsg(appctx, LOG_INFO, memprintf(&msg, "New version created: %u\n", next_gen));
}
return 0;
}
static void cli_release_show_map(struct appctx *appctx)
{
if (appctx->st2 == STAT_ST_LIST) {
@ -1017,11 +1047,13 @@ static struct cli_kw_list cli_kws = {{ },{
{ { "clear", "acl", NULL }, "clear acl [@ver] <id> : clear the content of this acl", cli_parse_clear_map, cli_io_handler_clear_map, NULL },
{ { "del", "acl", NULL }, "del acl : delete acl entry", cli_parse_del_map, NULL },
{ { "get", "acl", NULL }, "get acl : report the patterns matching a sample for an ACL", cli_parse_get_map, cli_io_handler_map_lookup, cli_release_mlook },
{ { "prepare","acl",NULL }, "prepare acl <id>: prepare a new version for atomic ACL replacement", cli_parse_prepare_map, NULL },
{ { "show", "acl", NULL }, "show acl [@ver] [id] : report available acls or dump an acl's contents", cli_parse_show_map, NULL },
{ { "add", "map", NULL }, "add map : add map entry", cli_parse_add_map, NULL },
{ { "clear", "map", NULL }, "clear map [@ver] <id> : clear the content of this map", cli_parse_clear_map, cli_io_handler_clear_map, NULL },
{ { "del", "map", NULL }, "del map : delete map entry", cli_parse_del_map, NULL },
{ { "get", "map", NULL }, "get map : report the keys and values matching a sample for a map", cli_parse_get_map, cli_io_handler_map_lookup, cli_release_mlook },
{ { "prepare","map",NULL }, "prepare map <id>: prepare a new version for atomic map replacement", cli_parse_prepare_map, NULL },
{ { "set", "map", NULL }, "set map : modify map entry", cli_parse_set_map, NULL },
{ { "show", "map", NULL }, "show map [@ver] [id] : report available maps or dump a map's contents", cli_parse_show_map, NULL },
{ { NULL }, NULL, NULL, NULL }