MAJOR: tools: support environment variables in addresses

Now that all addresses are parsed using str2sa_range(), it becomes easy
to add support for environment variables and use them everywhere an address
is needed. Environment variables are used as $VAR or ${VAR} as in shell.
Any number of variables may compose an address, allowing various fantasies
such as "fd@${FD_HTTP}" or "${LAN_DC1}.1:80".

These ones are usable in logs, bind, servers, peers, stats socket, source,
dispatch, and check address.
This commit is contained in:
Willy Tarreau 2013-03-11 01:20:04 +01:00
parent 40aa070c51
commit dad36a3ee3
3 changed files with 122 additions and 3 deletions

View File

@ -562,6 +562,11 @@ log <address> <facility> [max level [min level]]
the chroot) and uid/gid (be sure the path is appropriately
writeable).
Any part of the address string may reference any number of environment
variables by preceding their name with a dollar sign ('$') and
optionally enclosing them with braces ('{}'), similarly to what is done
in Bourne shell.
<facility> must be one of the 24 standard syslog facilities :
kern user mail daemon auth syslog lpr news
@ -1021,6 +1026,10 @@ peer <peername> <ip>:<port>
peer name. This makes it easier to maintain coherent configuration files
across all peers.
Any part of the address string may reference any number of environment
variables by preceding their name with a dollar sign ('$') and optionally
enclosing them with braces ('{}'), similarly to what is done in Bourne shell.
Example:
peers mypeers
peer haproxy1 192.168.0.1:1024
@ -1619,6 +1628,10 @@ bind /<path> [, ...] [param*]
- 'fd@<n>' -> use file descriptor <n> inherited from the
parent. The fd must be bound and may or may not already
be listening.
Any part of the address string may reference any number of
environment variables by preceding their name with a dollar
sign ('$') and optionally enclosing them with braces ('{}'),
similarly to what is done in Bourne shell.
<port_range> is either a unique TCP port, or a port range for which the
proxy will accept connections for the IP address specified
@ -1675,6 +1688,9 @@ bind /<path> [, ...] [param*]
bind ipv4@public_ssl:443 ssl crt /etc/haproxy/site.pem
bind unix@ssl-frontend.sock user root mode 600 accept-proxy
listen external_bind_app1
bind fd@${FD_APP1}
See also : "source", "option forwardfor", "unix-bind" and the PROXY protocol
documentation, and section 5 about bind options.
@ -2829,6 +2845,11 @@ no log
inside the chroot) and uid/gid (be sure the path is
appropriately writeable).
Any part of the address string may reference any number of
environment variables by preceding their name with a dollar
sign ('$') and optionally enclosing them with braces ('{}'),
similarly to what is done in Bourne shell.
<facility> must be one of the 24 standard syslog facilities :
kern user mail daemon auth syslog lpr news
@ -2862,6 +2883,8 @@ no log
log global
log 127.0.0.1:514 local0 notice # only send important events
log 127.0.0.1:514 local0 notice notice # same but limit output level
log ${LOCAL_SYSLOG}:514 local0 notice # send to local server
log-format <string>
Allows you to custom a log line.
@ -5094,6 +5117,10 @@ server <name> <address>[:[port]] [param*]
- 'ipv4@' -> address is always IPv4
- 'ipv6@' -> address is always IPv6
- 'unix@' -> address is a path to a local unix socket
Any part of the address string may reference any number of
environment variables by preceding their name with a dollar
sign ('$') and optionally enclosing them with braces ('{}'),
similarly to what is done in Bourne shell.
<port> is an optional port specification. If set, all connections will
be sent to this port. If unset, the same port the client
@ -5109,6 +5136,9 @@ server <name> <address>[:[port]] [param*]
server first 10.1.1.1:1080 cookie first check inter 1000
server second 10.1.1.2:1080 cookie second check inter 1000
server transp ipv4@
server backup ${SRV_BACKUP}:1080 backup
server www1_dc1 ${LAN_DC1}.101:80
server www1_dc2 ${LAN_DC2}.101:80
See also: "default-server", "http-send-name-header" and section 5 about
server options
@ -5133,6 +5163,10 @@ source <addr>[:<port>] [interface <name>]
- 'ipv4@' -> address is always IPv4
- 'ipv6@' -> address is always IPv6
- 'unix@' -> address is a path to a local unix socket
Any part of the address string may reference any number of
environment variables by preceding their name with a dollar
sign ('$') and optionally enclosing them with braces ('{}'),
similarly to what is done in Bourne shell.
<port> is an optional port. It is normally not needed but may be useful
in some very specific contexts. The default value of zero means

View File

@ -732,6 +732,14 @@ char *memprintf(char **out, const char *format, ...)
*/
char *indent_msg(char **out, int level);
/* Convert occurrences of environment variables in the input string to their
* corresponding value. A variable is identified as a series of alphanumeric
* characters or underscores following a '$' sign. The <in> string must be
* free()able. NULL returns NULL. The resulting string might be reallocated if
* some expansion is made.
*/
char *env_expand(char *in);
/* debugging macro to emit messages using write() on fd #-1 so that strace sees
* them.
*/

View File

@ -655,7 +655,7 @@ struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char
portl = porth = porta = 0;
str2 = back = strdup(str);
str2 = back = env_expand(strdup(str));
if (str2 == NULL) {
memprintf(err, "out of memory in '%s'\n", __FUNCTION__);
goto out;
@ -688,7 +688,7 @@ struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char
((struct sockaddr_in *)&ss)->sin_addr.s_addr = strtol(str2, &endptr, 10);
if (!*str2 || *endptr) {
memprintf(err, "file descriptor '%s' is not a valid integer\n", str2);
memprintf(err, "file descriptor '%s' is not a valid integer in '%s'\n", str2, str);
goto out;
}
@ -750,7 +750,7 @@ struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char
porta = porth;
}
else if (*port1) { /* other any unexpected char */
memprintf(err, "invalid character '%c' in port number '%s'\n", *port1, port1);
memprintf(err, "invalid character '%c' in port number '%s' in '%s'\n", *port1, port1, str);
goto out;
}
set_host_port(&ss, porta);
@ -1996,6 +1996,83 @@ char *indent_msg(char **out, int level)
return ret;
}
/* Convert occurrences of environment variables in the input string to their
* corresponding value. A variable is identified as a series of alphanumeric
* characters or underscores following a '$' sign. The <in> string must be
* free()able. NULL returns NULL. The resulting string might be reallocated if
* some expansion is made. Variable names may also be enclosed into braces if
* needed (eg: to concatenate alphanum characters).
*/
char *env_expand(char *in)
{
char *txt_beg;
char *out;
char *txt_end;
char *var_beg;
char *var_end;
char *value;
char *next;
int out_len;
int val_len;
if (!in)
return in;
value = out = NULL;
out_len = 0;
txt_beg = in;
do {
/* look for next '$' sign in <in> */
for (txt_end = txt_beg; *txt_end && *txt_end != '$'; txt_end++);
if (!*txt_end && !out) /* end and no expansion performed */
return in;
val_len = 0;
next = txt_end;
if (*txt_end == '$') {
char save;
var_beg = txt_end + 1;
if (*var_beg == '{')
var_beg++;
var_end = var_beg;
while (isalnum((int)(unsigned char)*var_end) || *var_end == '_') {
var_end++;
}
next = var_end;
if (*var_end == '}' && (var_beg > txt_end + 1))
next++;
/* get value of the variable name at this location */
save = *var_end;
*var_end = '\0';
value = getenv(var_beg);
*var_end = save;
val_len = value ? strlen(value) : 0;
}
out = realloc(out, out_len + (txt_end - txt_beg) + val_len + 1);
if (txt_end > txt_beg) {
memcpy(out + out_len, txt_beg, txt_end - txt_beg);
out_len += txt_end - txt_beg;
}
if (val_len) {
memcpy(out + out_len, value, val_len);
out_len += val_len;
}
out[out_len] = 0;
txt_beg = next;
} while (*txt_beg);
/* here we know that <out> was allocated and that we don't need <in> anymore */
free(in);
return out;
}
/*
* Local variables:
* c-indent-level: 8