diff --git a/doc/SPOE.txt b/doc/SPOE.txt index 961d32a43..7ce2bef84 100644 --- a/doc/SPOE.txt +++ b/doc/SPOE.txt @@ -172,8 +172,10 @@ spoe-agent - [no] option pipelining - [no] option send-frag-payload - option continue-on-error + - option force-set-var - option set-on-error - option var-prefix + - register-var-names - timeout hello|idle|processing - use-backend @@ -321,8 +323,24 @@ option var-prefix By default, an agent will never set new variables at runtime: It can only set new value for existing ones. If you want a different behaviour, see - force-set-var option + force-set-var option and register-var-names directive. +register-var-names ... + Register some variable names. By default, an agent will not be allowed to set + new variables at runtime. This rule can be totally relaxed by setting the + option "force-set-var". If you know all the variables you will need, this + directive is a good way to register them without letting an agent doing what + it want. This is only required if these variables are not referenced anywhere + in the HAProxy configuration or the SPOE one. + + Arguments: + is a variable name without the scope. The name may only + contain characters 'a-z', 'A-Z', '0-9', '.' and '_'. + + The prefix will be automatically added during the registration. You can have + many "register-var-names" lines. + + See also: "option force-set-var", "option var-prefix". timeout hello Set the maximum time to wait for an agent to receive the AGENT-HELLO frame. @@ -391,7 +409,6 @@ spoe-message acl [flags] [operator] ... - Declare or complete an access list. See section 7 about ACL usage in the HAProxy Configuration Manual. diff --git a/include/types/spoe.h b/include/types/spoe.h index 392cc94ef..2632601a7 100644 --- a/include/types/spoe.h +++ b/include/types/spoe.h @@ -177,6 +177,13 @@ struct spoe_placeholder { struct list list; /* Use to chain SPOE placeholders */ }; +/* Used during the config parsing, when SPOE agent section is parsed, to + * register some variable names. */ +struct spoe_var_placeholder { + char *name; /* The variable name */ + struct list list; /* Use to chain SPOE var placeholders */ +}; + /* Describe a message that will be sent in a NOTIFY frame. A message has a name, * an argument list (see above) and it is linked to a specific event. */ struct spoe_message { diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 1b69ee258..e70cf111e 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -87,6 +87,7 @@ struct list curmsgs; struct list curgrps; struct list curmphs; struct list curgphs; +struct list curvars; /* Pools used to allocate SPOE structs */ static struct pool_head *pool_head_spoe_ctx = NULL; @@ -3483,6 +3484,33 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) goto out; } } + else if (!strcmp(args[0], "register-var-names")) { + int cur_arg; + + if (!*args[1]) { + ha_alert("parsing [%s:%d] : '%s' expects one or more variable names.\n", + file, linenum, args[0]); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + cur_arg = 1; + while (*args[cur_arg]) { + struct spoe_var_placeholder *vph; + + if ((vph = calloc(1, sizeof(*vph))) == NULL) { + ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + if ((vph->name = strdup(args[cur_arg])) == NULL) { + ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + LIST_ADDQ(&curvars, &vph->list); + cur_arg++; + } + } else if (*args[0]) { ha_alert("parsing [%s:%d] : unknown keyword '%s' in spoe-agent section.\n", file, linenum, args[0]); @@ -3779,6 +3807,7 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px, struct spoe_message *msg, *msgback; struct spoe_group *grp, *grpback; struct spoe_placeholder *ph, *phback; + struct spoe_var_placeholder *vph, *vphback; char *file = NULL, *engine = NULL; int ret, pos = *cur_arg + 1; @@ -3834,6 +3863,7 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px, LIST_INIT(&curgrps); LIST_INIT(&curmphs); LIST_INIT(&curgphs); + LIST_INIT(&curvars); ret = readcfgfile(file); curproxy = NULL; @@ -4061,6 +4091,25 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px, LIST_DEL(&ph->list); spoe_release_placeholder(ph); } + list_for_each_entry_safe(vph, vphback, &curvars, list) { + struct arg arg; + + trash.len = snprintf(trash.str, trash.size, "proc.%s.%s", + curagent->var_pfx, vph->name); + + arg.type = ARGT_STR; + arg.data.str.str = trash.str; + arg.data.str.len = trash.len; + if (!vars_check_arg(&arg, err)) { + memprintf(err, "SPOE agent '%s': failed to register variable %s.%s (%s)", + curagent->id, curagent->var_pfx, vph->name, *err); + goto error; + } + + LIST_DEL(&vph->list); + free(vph->name); + free(vph); + } list_for_each_entry_safe(grp, grpback, &curgrps, list) { LIST_DEL(&grp->list); spoe_release_group(grp); @@ -4081,6 +4130,11 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px, LIST_DEL(&ph->list); spoe_release_placeholder(ph); } + list_for_each_entry_safe(vph, vphback, &curvars, list) { + LIST_DEL(&vph->list); + free(vph->name); + free(vph); + } list_for_each_entry_safe(grp, grpback, &curgrps, list) { LIST_DEL(&grp->list); spoe_release_group(grp);