Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

Commit af1f237

Browse files
author
Feng Honglin
authored
Merge pull request #192 from docker/staging
1.6.6
2 parents ef61092 + 4800bc0 commit af1f237

17 files changed

+163
-102
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,4 @@ nosetests.xml
4040
.pydevproject
4141
.idea
4242
.DS_Store
43+
.vagrant/

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ Settings in this part is immutable, you have to redeploy HAProxy service to make
199199
|Environment Variable|Default|Description|
200200
|:-----:|:-----:|:----------|
201201
|ADDITIONAL_BACKEND_\<NAME\>| |add an additional backend with the name set in <NAME>. Possible values include:`balance source, server 127.0.0.1:8080`|
202+
|ADDITIONAL_BACKEND_FILE_\<NAME\>| add an additional backend with the name set in <NAME> and value of the contents of specified file.
202203
|ADDITIONAL_SERVICES| |list of additional services to balance (es: `prj1:web,prj2:sql`). Discovery will be based on `com.docker.compose.[project|service]` container labels. This environment variable only works on compose v2, and the referenced services must be on a network resolvable and accessible to this containers.|
203204
|BALANCE|roundrobin|load balancing algorithm to use. Possible values include: `roundrobin`, `static-rr`, `source`, `leastconn`. See:[HAProxy:balance](https://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-balance)|
204205
|CA_CERT_FILE| |the path of a ca-cert file. This allows you to mount your ca-cert file directly from a volume instead of from envvar. If set, `CA_CERT` envvar will be ignored. Possible value: `/cacerts/cert0.pem`|
@@ -207,8 +208,11 @@ Settings in this part is immutable, you have to redeploy HAProxy service to make
207208
|DEFAULT_SSL_CERT| |Default ssl cert, a pem file content with private key followed by public certificate, '\n'(two chars) as the line separator. should be formatted as one line - see [SSL Termination](#ssl-termination)|
208209
|EXTRA_BIND_SETTINGS| |comma-separated string(`<port>:<setting>`) of extra settings, and each part will be appended to the related port bind section in the configuration file. To escape comma, use `\,`. Possible value: `443:accept-proxy, 80:name http`|
209210
|EXTRA_DEFAULT_SETTINGS| |comma-separated string of extra settings, and each part will be appended to DEFAULT section in the configuration file. To escape comma, use `\,`|
211+
|EXTRA_DEFAULT_SETTINGS_FILE|File whose contents will be included in the DEFAULT section of the configuration file.|
210212
|EXTRA_FRONTEND_SETTINGS_\<PORT\>| |comma-separated string of extra settings, and each part will be appended frontend section with the port number specified in the name of the envvar. To escape comma, use `\,`. E.g. `EXTRA_FRONTEND_SETTINGS_80=balance source, maxconn 2000`|
213+
|EXTRA_DEFAULT_SETTINGS_FILE_\<PORT\>|File whose contents will be appended to the frontend section with the port number specified in the filename.|
211214
|EXTRA_GLOBAL_SETTINGS| |comma-separated string of extra settings, and each part will be appended to GLOBAL section in the configuration file. To escape comma, use `\,`. Possible value: `tune.ssl.cachesize 20000, tune.ssl.default-dh-param 2048`|
215+
|EXTRA_GLOBAL_SETTINGS_FILE|File whose contents will be included in the GLOBAL section of the configuration file.|
212216
|EXTRA_ROUTE_SETTINGS| |a string which is append to the each backend route after the health check, can be over written in the linked services. Possible value: "send-proxy"|
213217
|EXTRA_SSL_CERTS| |list of extra certificate names separated by comma, eg. `CERT1, CERT2, CERT3`. You also need to specify each certificate as separate env variables like so: `CERT1="<cert-body1>"`, `CERT2="<cert-body2>"`, `CERT3="<cert-body3>"`|
214218
|FORCE_DEFAULT_BACKEND| True | set the default_service as a default backend. This is useful when you have more than one backend and you don't want your default_service as a default backend
@@ -238,7 +242,6 @@ Settings here can overwrite the settings in HAProxy, which are only applied to t
238242

239243
|Environment Variable|Description|
240244
|:-----:|:----------|
241-
|APPSESSION|sticky session option, possible value `JSESSIONID len 52 timeout 3h`. See:[HAProxy:appsession](http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-appsession)|
242245
|BALANCE|load balancing algorithm to use. Possible values include: `roundrobin`, `static-rr`, `source`, `leastconn`. See:[HAProxy:balance](https://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-balance)|
243246
|COOKIE|sticky session option. Possible value `SRV insert indirect nocache`. See:[HAProxy:cookie](http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-cookie)|
244247
|DEFAULT_SSL_CERT|similar to SSL_CERT, but stores the pem file at `/certs/cert0.pem` as the default ssl certs. If multiple `DEFAULT_SSL_CERT` are specified in linked services and HAProxy, the behavior is undefined|
@@ -363,10 +366,9 @@ Copy the output and set it as the value of `SSL_CERT` or `DEFAULT_SSL_CERT`.
363366
There are three method to setup affinity and sticky session:
364367

365368
1. set `BALANCE=source` in your application service. When setting `source` method of balance, HAProxy will hash the client IP address and make sure that the same IP always goes to the same server.
366-
2. set `APPSESSION=<value>`. use application session to determine which server a client should connect to. Possible value of `<value>` could be `JSESSIONID len 52 timeout 3h`
367369
2. set `COOKIE=<value>`. use application cookie to determine which server a client should connect to. Possible value of `<value>` could be `SRV insert indirect nocache`
368370

369-
Check [HAProxy:appsession](http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-appsession) and [HAProxy:cookie](http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-cookie) for more information.
371+
Check [HAProxy:cookie](http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-cookie) for more information.
370372

371373

372374
## TCP load balancing

haproxy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.6.5"
1+
__version__ = "1.6.6"

haproxy/config.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import logging
12
import os
23
import re
34

5+
logger = logging.getLogger("haproxy")
6+
47

58
class RunningMode():
69
LegacyMode, ComposeMode, SwarmMode, CloudMode = range(4)
@@ -21,11 +24,24 @@ def parse_extra_frontend_settings(envvars):
2124
settings_dict = {}
2225
if isinstance(envvars, os._Environ) or isinstance(envvars, dict):
2326
frontend_settings_pattern = re.compile(r"^EXTRA_FRONTEND_SETTINGS_(\d{1,5})$")
27+
frontend_settings_file_pattern = re.compile(r"^EXTRA_FRONTEND_SETTINGS_FILE_(\d{1,5})$")
2428
for k, v in envvars.iteritems():
29+
settings = []
2530
match = frontend_settings_pattern.match(k)
31+
file_match = frontend_settings_file_pattern.match(k)
2632
if match:
2733
port = match.group(1)
28-
settings = [x.strip().replace("\,", ",") for x in re.split(r'(?<!\\),', v.strip())]
34+
settings.extend([x.strip().replace("\,", ",") for x in re.split(r'(?<!\\),', v.strip())])
35+
elif file_match:
36+
port = file_match.group(1)
37+
try:
38+
with open(v) as file:
39+
for line in file:
40+
settings.append(line.strip())
41+
except Exception as e:
42+
logger.info("Error reading %s at '%s', error %s" % (k, v, e))
43+
44+
if len(settings) > 0:
2945
if port in settings_dict:
3046
settings_dict[port].extend(settings)
3147
else:
@@ -36,12 +52,26 @@ def parse_extra_frontend_settings(envvars):
3652
def parse_additional_backend_settings(envvars):
3753
settings_dict = {}
3854
if isinstance(envvars, os._Environ) or isinstance(envvars, dict):
39-
frontend_settings_pattern = re.compile(r"^ADDITIONAL_BACKEND_(\w{1,9})$")
55+
additional_backend_pattern = re.compile(r"^ADDITIONAL_BACKEND_(\w+)$")
56+
additional_backend_file_pattern = re.compile(r"^ADDITIONAL_BACKEND_FILE_(\w+)$")
4057
for k, v in envvars.iteritems():
41-
match = frontend_settings_pattern.match(k)
42-
if match:
58+
settings = []
59+
match = additional_backend_pattern.match(k)
60+
file_match = additional_backend_file_pattern.match(k)
61+
62+
if file_match:
63+
server = file_match.group(1)
64+
try:
65+
with open(v) as f:
66+
for line in f:
67+
settings.append(line.strip())
68+
except Exception as e:
69+
logger.info("Error reading %s at '%s', error %s" % (k, v, e))
70+
elif match:
4371
server = match.group(1)
44-
settings = [x.strip().replace("\,", ",") for x in re.split(r'(?<!\\),', v.strip())]
72+
settings.extend([x.strip().replace("\,", ",") for x in re.split(r'(?<!\\),', v.strip())])
73+
74+
if len(settings) > 0:
4575
if server in settings_dict:
4676
settings_dict[server].extend(settings)
4777
else:
@@ -61,8 +91,10 @@ def parse_additional_backend_settings(envvars):
6191
DEFAULT_SSL_CERT = os.getenv("DEFAULT_SSL_CERT") or os.getenv("SSL_CERT")
6292
EXTRA_BIND_SETTINGS = parse_extra_bind_settings(os.getenv("EXTRA_BIND_SETTINGS"))
6393
EXTRA_DEFAULT_SETTINGS = os.getenv("EXTRA_DEFAULT_SETTINGS")
94+
EXTRA_DEFAULT_SETTINGS_FILE = os.getenv("EXTRA_DEFAULT_SETTINGS_FILE")
6495
EXTRA_FRONTEND_SETTINGS = parse_extra_frontend_settings(os.environ)
6596
EXTRA_GLOBAL_SETTINGS = os.getenv("EXTRA_GLOBAL_SETTINGS")
97+
EXTRA_GLOBAL_SETTINGS_FILE = os.getenv("EXTRA_GLOBAL_SETTINGS_FILE")
6698
EXTRA_SSL_CERT = os.getenv("EXTRA_SSL_CERTS")
6799
EXTRA_ROUTE_SETTINGS = os.getenv("EXTRA_ROUTE_SETTINGS", "")
68100
FORCE_DEFAULT_BACKEND = os.getenv("FORCE_DEFAULT_BACKEND", "True")

haproxy/haproxycfg.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import copy
2-
import logging
32
import time
43
from collections import OrderedDict
54

@@ -256,7 +255,16 @@ def _config_global_section():
256255
statements.extend(ConfigHelper.config_ssl_bind_options(SSL_BIND_OPTIONS))
257256
statements.extend(ConfigHelper.config_ssl_bind_ciphers(SSL_BIND_CIPHERS))
258257
statements.extend(ConfigHelper.config_extra_settings(EXTRA_GLOBAL_SETTINGS))
258+
if EXTRA_GLOBAL_SETTINGS_FILE:
259+
try:
260+
with open(EXTRA_GLOBAL_SETTINGS_FILE) as file:
261+
for line in file:
262+
statements.append(line.strip())
263+
except Exception as e:
264+
logger.info(
265+
"Error reading EXTRA_GLOBAL_SETTINGS_FILE at '%s', error %s" % (EXTRA_GLOBAL_SETTINGS_FILE, e))
259266
cfg["global"] = statements
267+
260268
return cfg
261269

262270
@staticmethod
@@ -285,7 +293,14 @@ def _config_defaults_section():
285293
statements.extend(ConfigHelper.config_option(OPTION))
286294
statements.extend(ConfigHelper.config_timeout(TIMEOUT))
287295
statements.extend(ConfigHelper.config_extra_settings(EXTRA_DEFAULT_SETTINGS))
288-
296+
if EXTRA_DEFAULT_SETTINGS_FILE:
297+
try:
298+
with open(EXTRA_DEFAULT_SETTINGS_FILE) as file:
299+
for line in file:
300+
statements.append(line.strip())
301+
except Exception as e:
302+
logger.info(
303+
"Error reading EXTRA_DEFAULT_SETTINGS_FILE at '%s', error %s" % (EXTRA_DEFAULT_SETTINGS_FILE, e))
289304
cfg["defaults"] = statements
290305
return cfg
291306

@@ -358,11 +373,10 @@ def _config_frontend_sections(self):
358373
port_str = "frontend port_%s" % port
359374
if port_str in cfg:
360375
del cfg[port_str]
361-
362376
else:
363377
self.require_default_route = FrontendHelper.check_require_default_route(self.specs.get_routes(),
364378
self.routes_added)
365-
if self.require_default_route:
379+
if self.require_default_route or EXTRA_FRONTEND_SETTINGS:
366380
cfg, monitor_uri_configured = FrontendHelper.config_default_frontend(ssl_bind_string)
367381
else:
368382
cfg = OrderedDict()

haproxy/helper/backend_helper.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,6 @@ def get_sticky_setting(details, service_alias):
100100
setting = []
101101
is_sticky = False
102102

103-
appsession = get_service_attribute(details, "appsession", service_alias)
104-
if appsession:
105-
setting.append("appsession %s" % appsession)
106-
is_sticky = True
107-
108103
cookie = get_service_attribute(details, "cookie", service_alias)
109104
if cookie:
110105
setting.append("cookie %s" % cookie)

haproxy/helper/frontend_helper.py

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -137,48 +137,50 @@ def get_bind_string(port, ssl_bind_string, vhosts):
137137
def config_default_frontend(ssl_bind_string):
138138
cfg = OrderedDict()
139139
monitor_uri_configured = False
140-
frontend = [("bind :80 %s" % EXTRA_BIND_SETTINGS.get('80', "")).strip()]
141-
142-
# add x-forwarded-porto header if not skipped
143-
if not SKIP_FORWARDED_PROTO:
144-
frontend.append("reqadd X-Forwarded-Proto:\ http")
145-
146-
frontend.append("maxconn %s" % MAXCONN)
147-
148-
if MONITOR_URI and MONITOR_PORT == '80':
149-
frontend.append("monitor-uri %s" % MONITOR_URI)
150-
monitor_uri_configured = True
151-
152-
if "80" in EXTRA_FRONTEND_SETTINGS:
153-
frontend.extend(EXTRA_FRONTEND_SETTINGS["80"])
140+
monitor_uri_configured_80 = False
141+
monitor_uri_configured_443 = False
142+
monitor_uri_configured_port = False
143+
if EXTRA_FRONTEND_SETTINGS:
144+
is_monitor_uri_configured = False
145+
for port in EXTRA_FRONTEND_SETTINGS.keys():
146+
frontend, is_monitor_uri_configured_port = config_default_frontend_by_port(port, ssl_bind_string)
147+
cfg["frontend default_port_%s" % port] = frontend
148+
is_monitor_uri_configured = is_monitor_uri_configured or is_monitor_uri_configured_port
149+
monitor_uri_configured_port = monitor_uri_configured_port or is_monitor_uri_configured
150+
else:
151+
frontend, monitor_uri_configured_80 = config_default_frontend_by_port("80", "")
152+
cfg["frontend default_port_80"] = frontend
153+
if ssl_bind_string:
154+
frontend_ssl, monitor_uri_configured_443 = config_default_frontend_by_port("443", ssl_bind_string)
155+
cfg["frontend default_port_443"] = frontend_ssl
154156

155-
if "True" in FORCE_DEFAULT_BACKEND:
156-
frontend.append("default_backend default_service")
157+
return cfg, monitor_uri_configured or monitor_uri_configured_80 or monitor_uri_configured_443 or monitor_uri_configured_port
157158

158-
cfg["frontend default_port_80"] = frontend
159159

160+
def config_default_frontend_by_port(port, ssl_bind_string):
161+
monitor_uri_configured = False
160162
if ssl_bind_string:
161-
ssl_frontend = [("bind :443 %s %s" % (ssl_bind_string, EXTRA_BIND_SETTINGS.get('443', ""))).strip()]
162-
163+
frontend = [("bind :%s %s %s" % (port, ssl_bind_string, EXTRA_BIND_SETTINGS.get(port, ""))).strip()]
163164
# add x-forwarded-porto header if not skipped
164165
if not SKIP_FORWARDED_PROTO:
165-
ssl_frontend.append("reqadd X-Forwarded-Proto:\ https")
166-
167-
ssl_frontend.append("maxconn %s" % MAXCONN)
168-
169-
if MONITOR_URI and (MONITOR_PORT == '443'):
170-
ssl_frontend.append("monitor-uri %s" % MONITOR_URI)
171-
monitor_uri_configured = True
166+
frontend.append("reqadd X-Forwarded-Proto:\ https")
167+
else:
168+
frontend = [("bind :%s %s" % (port, EXTRA_BIND_SETTINGS.get(port, ""))).strip()]
169+
if not SKIP_FORWARDED_PROTO:
170+
frontend.append("reqadd X-Forwarded-Proto:\ http")
172171

173-
if "443" in EXTRA_FRONTEND_SETTINGS:
174-
ssl_frontend.extend(EXTRA_FRONTEND_SETTINGS["443"])
172+
frontend.append("maxconn %s" % MAXCONN)
175173

176-
if "True" in FORCE_DEFAULT_BACKEND:
177-
ssl_frontend.append("default_backend default_service")
174+
if MONITOR_URI and MONITOR_PORT == port:
175+
frontend.append("monitor-uri %s" % MONITOR_URI)
176+
monitor_uri_configured = True
178177

179-
cfg["frontend default_port_443"] = ssl_frontend
178+
if port in EXTRA_FRONTEND_SETTINGS:
179+
frontend.extend(EXTRA_FRONTEND_SETTINGS[port])
180180

181-
return cfg, monitor_uri_configured
181+
if "True" in FORCE_DEFAULT_BACKEND:
182+
frontend.append("default_backend default_service")
183+
return frontend, monitor_uri_configured
182184

183185

184186
def config_monitor_frontend(monitor_uri_configured):

haproxy/helper/swarm_mode_link_helper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def get_task_links(tasks, services, haproxy_service_id, haproxy_nets):
4545
task_slot = "%d" % task.get("Slot", 0)
4646
task_service_id = task.get("ServiceID", "")
4747
task_service_name = services_id_name.get(task_service_id, "")
48-
task_labels = services_id_labels.get(task_service_id)
48+
task_labels = services_id_labels.get(task_service_id, {})
4949

5050
if task_labels.get(LABEL_SWARM_MODE_DEACTIVATE, "").lower() == "true":
5151
continue

haproxy/main.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from config import RunningMode
2424

2525
dockercloud.user_agent = "dockercloud-haproxy/%s" % __version__
26+
dockercloud.api_timeout = 15
2627

2728
logger = logging.getLogger("haproxy")
2829

haproxy/parser/base_parser.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,6 @@ def parse_virtual_host(value):
133133
def parse_force_ssl(value):
134134
return value
135135

136-
@staticmethod
137-
def parse_appsession(value):
138-
return value
139-
140136
@staticmethod
141137
def parse_balance(value):
142138
return value

0 commit comments

Comments
 (0)