MINOR: config: support some pseudo-variables for file/line/section

The new pseudo-variables ".FILE", ".LINE" and ".SECTION" will be resolved
on the fly by the config parser and will respectively retrieve the current
configuration file name, the current line number and the current section
being parsed. This may help emit logs, errors, and debugging information
(e.g. which rule matched).

The '.' in the first char was reserved for such pseudo-variables and no
other variable is permitted. This will allow to add support for new ones
in the future if they prove to be useful (e.g. randoms/uuid for secret
keying or automatic naming of configuration objects).
This commit is contained in:
Willy Tarreau 2021-05-06 10:25:11 +02:00
parent 5150805a5c
commit a46f1af2b1
2 changed files with 45 additions and 3 deletions

View File

@ -746,6 +746,29 @@ file, or could be inherited by a program (See 3.7. Programs):
* HAPROXY_MASTER_CLI: In master-worker mode, listeners addresses of the master
CLI, separated by semicolons.
In addition, some pseudo-variables are internally resolved and may be used as
regular variables. Pseudo-variables always start with a dot ('.'), and are the
only ones where the dot is permitted. The current list of pseudo-variables is:
* .FILE: the name of the configuration file currently being parsed.
* .LINE: the line number of the configuration file currently being parsed,
starting at one.
* .SECTION: the name of the section currently being parsed, or its type if the
section doesn't have a name (e.g. "global"), or an empty string before the
first section.
These variables are resolved at the location where they are parsed. For example
if a ".LINE" variable is used in a "log-format" directive located in a defaults
section, its line number will be resolved before parsing and compiling the
"log-format" directive, so this same line number will be reused by subsequent
proxies.
This way it is possible to emit information to help locate a rule in variables,
logs, error statuses, health checks, header values, or even to use line numbers
to name some config objects like servers for example.
See also "external-check command" for other variables.

View File

@ -5300,14 +5300,14 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg
*/
char *var_name;
char save_char;
char *value;
const char *value;
in++;
if (*in == '{')
brace = in++;
if (!isalpha((unsigned char)*in) && *in != '_') {
if (!isalpha((unsigned char)*in) && *in != '_' && *in != '.') {
/* unacceptable character in variable name */
err |= PARSE_ERR_VARNAME;
if (errptr)
@ -5316,12 +5316,31 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg
}
var_name = in;
if (*in == '.')
in++;
while (isalnum((unsigned char)*in) || *in == '_')
in++;
save_char = *in;
*in = '\0';
value = getenv(var_name);
if (unlikely(*var_name == '.')) {
/* internal pseudo-variables */
if (strcmp(var_name, ".LINE") == 0)
value = ultoa(global.cfg_curr_line);
else if (strcmp(var_name, ".FILE") == 0)
value = global.cfg_curr_file;
else if (strcmp(var_name, ".SECTION") == 0)
value = global.cfg_curr_section;
else {
/* unsupported internal variable name */
err |= PARSE_ERR_VARNAME;
if (errptr)
*errptr = var_name;
goto leave;
}
} else {
value = getenv(var_name);
}
*in = save_char;
/* support for '[*]' sequence to force word expansion,