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.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 86d88a9..5254527 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -562,6 +562,11 @@
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 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 @@
- '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 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 @@
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 @@
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 @@
- '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 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 @@
- '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
diff --git a/include/common/standard.h b/include/common/standard.h
index f9f21b0..8e88ee5 100644
--- a/include/common/standard.h
+++ b/include/common/standard.h
@@ -732,6 +732,14 @@
*/
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.
*/
diff --git a/src/standard.c b/src/standard.c
index cc22ba7..7a6ca11 100644
--- a/src/standard.c
+++ b/src/standard.c
@@ -655,7 +655,7 @@
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_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 @@
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 @@
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