MINOR: map/acl: add the "commit map/acl" CLI command
The command is used to atomically replace a map/acl with the pending contents of the designated version. The new version must have been allocated by "prepare map/acl" prior to this. At the moment it is not possible to force the version when adding new entries, so this may only be used to atomically clear an ACL/map.
This commit is contained in:
parent
97218ce3a9
commit
7a562ca809
|
@ -1557,6 +1557,35 @@ clear table <table> [ data.<type> <operator> <value> ] | [ key <key> ]
|
|||
$ echo "show table http_proxy" | socat stdio /tmp/sock1
|
||||
>>> # table: http_proxy, type: ip, size:204800, used:1
|
||||
|
||||
commit acl @<ver> <acl>
|
||||
Commit all changes made to version <ver> of ACL <acl>, and deletes all past
|
||||
versions. <acl> is the #<id> or the <file> returned by "show acl". The
|
||||
version number must be between "curr_ver"+1 and "next_ver" as reported in
|
||||
"show acl". The contents to be committed to the ACL can be consulted with
|
||||
"show acl @<ver> <acl>" if desired. The specified version number has normally
|
||||
been created with the "prepare acl" command. The replacement is atomic. It
|
||||
consists in atomically updating the current version to the specified version,
|
||||
which will instantly cause all entries in other versions to become invisible,
|
||||
and all entries in the new version to become visible. It is also possible to
|
||||
use this command to perform an atomic removal of all visible entries of an
|
||||
ACL by calling "prepare acl" first then committing without adding any
|
||||
entries. This command cannot be used if the reference <acl> is a file also
|
||||
used as a map. In this case, the "commit map" command must be used instead.
|
||||
|
||||
commit map @<ver> <map>
|
||||
Commit all changes made to version <ver> of map <map>, and deletes all past
|
||||
versions. <map> is the #<id> or the <file> returned by "show map". The
|
||||
version number must be between "curr_ver"+1 and "next_ver" as reported in
|
||||
"show map". The contents to be committed to the map can be consulted with
|
||||
"show map @<ver> <map>" if desired. The specified version number has normally
|
||||
been created with the "prepare map" command. The replacement is atomic. It
|
||||
consists in atomically updating the current version to the specified version,
|
||||
which will instantly cause all entries in other versions to become invisible,
|
||||
and all entries in the new version to become visible. It is also possible to
|
||||
use this command to perform an atomic removal of all visible entries of an
|
||||
map by calling "prepare map" first then committing without adding any
|
||||
entries.
|
||||
|
||||
commit ssl cert <filename>
|
||||
Commit a temporary SSL certificate update transaction.
|
||||
|
||||
|
|
66
src/map.c
66
src/map.c
|
@ -1040,17 +1040,83 @@ static int cli_parse_clear_map(char **args, char *payload, struct appctx *appctx
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* note: sets appctx->ctx.cli.i0 and appctx->ctx.cli.i1 to the oldest and
|
||||
* latest generations to clear, respectively, and will call the clear_map
|
||||
* handler.
|
||||
*/
|
||||
static int cli_parse_commit_map(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (strcmp(args[1], "map") == 0 || strcmp(args[1], "acl") == 0) {
|
||||
const char *gen = NULL;
|
||||
uint genid;
|
||||
uint ret;
|
||||
|
||||
/* 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;
|
||||
|
||||
if (*args[2] != '@')
|
||||
return cli_err(appctx, "Missing version number.\n");
|
||||
|
||||
/* The generation number is mandatory for a commit. The range
|
||||
* of generations that get trashed by a commit starts from the
|
||||
* opposite of the current one and ends at the previous one.
|
||||
*/
|
||||
gen = args[2] + 1;
|
||||
genid = str2uic(gen);
|
||||
appctx->ctx.cli.i1 = genid - 1;
|
||||
appctx->ctx.cli.i0 = appctx->ctx.cli.i1 - ((~0U) >> 1);
|
||||
|
||||
/* no parameter */
|
||||
if (!*args[3]) {
|
||||
if (appctx->ctx.map.display_flags == PAT_REF_MAP)
|
||||
return cli_err(appctx, "Missing map identifier.\n");
|
||||
else
|
||||
return cli_err(appctx, "Missing ACL identifier.\n");
|
||||
}
|
||||
|
||||
/* lookup into the refs and check the map flag */
|
||||
appctx->ctx.map.ref = pat_ref_lookup_ref(args[3]);
|
||||
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");
|
||||
}
|
||||
|
||||
HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||
if (genid - (appctx->ctx.map.ref->curr_gen + 1) <
|
||||
appctx->ctx.map.ref->next_gen - appctx->ctx.map.ref->curr_gen)
|
||||
ret = pat_ref_commit(appctx->ctx.map.ref, genid);
|
||||
else
|
||||
ret = 1;
|
||||
HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||
|
||||
if (ret != 0)
|
||||
return cli_err(appctx, "Version number out of range.\n");
|
||||
|
||||
/* delegate the clearing to the I/O handler which can yield */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* register cli keywords */
|
||||
|
||||
static struct cli_kw_list cli_kws = {{ },{
|
||||
{ { "add", "acl", NULL }, "add acl : add acl entry", cli_parse_add_map, NULL },
|
||||
{ { "clear", "acl", NULL }, "clear acl [@ver] <id> : clear the content of this acl", cli_parse_clear_map, cli_io_handler_clear_map, NULL },
|
||||
{ { "commit","acl", NULL }, "commit acl @<ver> <id> : commit the ACL at this version", cli_parse_commit_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 },
|
||||
{ { "commit","map", NULL }, "commit map @<ver> <id> : commit the map at this version", cli_parse_commit_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 },
|
||||
|
|
Loading…
Reference in New Issue