Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,13 +248,13 @@ Settings here can overwrite the settings in HAProxy, which are only applied to t
|EXCLUDE_PORTS|if set, the application by the application services to the backend routes. You can exclude the ports that you don't want to be routed, like database port|
|EXCLUDE_BASIC_AUTH|if set(any value) and `HTTP_BASIC_AUTH` global setting is set, no basic auth will be applied to this service.|
|EXTRA_ROUTE_SETTINGS|a string which is append to the each backend route after the health check,possible value: "send-proxy"|
|FAILOVER|if set (any value), this service will run as a HAProxy `backup` for other configured service(s) in the same backend|
|EXTRA_SETTINGS|comma-separated string of extra settings, and each part will be appended to either related backend section or listen session in the configuration file. To escape comma, use `\,`. Possible value: `balance source`|
|FAILOVER|if set(any value), it configures this service to be run as HAProxy `backup` for other configured service(s) in this backend|
|FORCE_SSL|if set(any value) together with ssl termination enabled. HAProxy will redirect HTTP request to HTTPS request.
|GZIP_COMPRESSION_TYPE|enable gzip compression. The value of this envvar is a list of MIME types that will be compressed. Some possible values: `text/html text/plain text/css application/javascript`. See:[HAProxy:compression](http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-compression)|
|HEALTH_CHECK|set health check on each backend route, possible value: "check inter 2000 rise 2 fall 3". See:[HAProxy:check](https://cbonte.github.io/haproxy-dconv/configuration-1.5.html#5.2-check)|
|HSTS_MAX_AGE|enable HSTS. It is an integer representing the max age of HSTS in seconds, possible value: `31536000`|
|HTTP_CHECK|enable HTTP protocol to check on the servers health, possible value: "OPTIONS * HTTP/1.1\r\nHost:\ www". See:[HAProxy:httpchk](https://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-option%20httpchk)|
|HTTP_CHECK|enable HTTP protocol to check on the servers health, possible value: "OPTIONS / HTTP/1.1\r\nHost:\ www". See:[HAProxy:httpchk](https://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-option%20httpchk)|
|OPTION|comma-separated list of HAProxy `option` entries. `option` specified here will be added to related backend or listen part, and overwrite the OPTION settings in the HAProxy container|
|SSL_CERT|ssl cert, a pem file with private key followed by public certificate, '\n'(two chars) as the line separator|
|TCP_PORTS|comma separated ports(e.g. 9000, 9001, 2222/ssl). The port listed in `TCP_PORTS` will be load-balanced in TCP mode. Port ends with `/ssl` indicates that port needs SSL termination.
Expand Down
33 changes: 11 additions & 22 deletions haproxy/helper/backend_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,13 @@ def get_backend_section(details, routes, vhosts, service_alias, routes_added):
backend_settings, is_sticky = get_backend_settings(details, service_alias, HTTP_BASIC_AUTH)
backend.extend(backend_settings)

route_health_check = get_route_health_check(details, service_alias, HEALTH_CHECK)
extra_route_settings = get_extra_route_settings(details, service_alias, EXTRA_ROUTE_SETTINGS)
route_setting = " ".join([route_health_check, extra_route_settings]).strip()
backend_routes = get_backend_routes(route_setting, is_sticky, routes, routes_added, service_alias, details)
backend_routes = get_backend_routes(is_sticky, routes, routes_added, service_alias)
backend.extend(backend_routes)

return backend


def get_backend_routes(route_setting, is_sticky, routes, routes_added, service_alias, details):
def get_backend_routes(is_sticky, routes, routes_added, service_alias):
backend_routes = []
for _service_alias, routes in routes.iteritems():
if not service_alias or _service_alias == service_alias:
Expand All @@ -38,29 +35,21 @@ def get_backend_routes(route_setting, is_sticky, routes, routes_added, service_a
if is_sticky:
backend_route.append("cookie %s" % route["container_name"])

if route_setting:
backend_route.append(route_setting)
if "health_check" in route and route["health_check"]:
backend_route.append(route["health_check"])
else:
backend_route.append(HEALTH_CHECK)

if details.get(service_alias, {}).get('failover', False):
backend_route.append("backup")
if "extra_route_settings" in route and route["extra_route_settings"]:
backend_route.append(route["extra_route_settings"])
else:
backend_route.append(EXTRA_ROUTE_SETTINGS)

backend_routes.append(" ".join(backend_route))
backend_routes.append(" ".join(backend_route).strip())

return sorted(backend_routes)


def get_route_health_check(details, service_alias, default_health_check):
health_check = get_service_attribute(details, "health_check", service_alias)
health_check = health_check if health_check else default_health_check
return health_check


def get_extra_route_settings(details, service_alias, default_extra_route_settings):
extra_route_settings = get_service_attribute(details, "extra_route_settings", service_alias)
extra_route_settings = extra_route_settings if extra_route_settings else default_extra_route_settings
return extra_route_settings


def get_websocket_setting(vhosts, service_alias):
websocket_setting = []
for v in vhosts:
Expand Down
15 changes: 15 additions & 0 deletions haproxy/parser/legacy_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,21 @@ def _parse_routes(details, envvars):
route = haproxy.config.BACKEND_MATCH.match(value).groupdict()

route.update({"container_name": container_name})

route_health_check = details.get(service_alias, {}).get("health_check")
if route_health_check:
route.update({"health_check": route_health_check})

failover = None
if details.get(service_alias, {}).get("failover"):
failover = "backup"

extra_route_settings = details.get(service_alias, {}).get("extra_route_settings")
extra_route_settings = " ".join([(extra_route_settings if extra_route_settings else ""),
(failover if failover else "")]).strip()
if extra_route_settings:
route.update({"extra_route_settings": extra_route_settings})

exclude_ports = details.get(service_alias, {}).get("exclude_ports")
if not exclude_ports or (exclude_ports and route["port"] not in exclude_ports):
if service_alias in routes:
Expand Down
15 changes: 15 additions & 0 deletions haproxy/parser/new_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,21 @@ def _parse_routes(details, links):
for endpoint in link["endpoints"].itervalues():
route = haproxy.config.BACKEND_MATCH.match(endpoint).groupdict()
route.update({"container_name": container_name})

route_health_check = details.get(service_alias, {}).get("health_check")
if route_health_check:
route.update({"health_check": route_health_check})

failover = None
if details.get(service_alias, {}).get("failover"):
failover = "backup"

extra_route_settings = details.get(service_alias, {}).get("extra_route_settings")
extra_route_settings = " ".join([(extra_route_settings if extra_route_settings else ""),
(failover if failover else "")]).strip()
if extra_route_settings:
route.update({"extra_route_settings": extra_route_settings})

exclude_ports = details.get(service_alias, {}).get("exclude_ports", [])
if not exclude_ports or (exclude_ports and route["port"] not in exclude_ports):
if route not in routes[service_alias]:
Expand Down
96 changes: 23 additions & 73 deletions tests/unit/helper/test_backend_helper.py
Original file line number Diff line number Diff line change
@@ -1,95 +1,45 @@
import unittest

from haproxy.helper.backend_helper import *

from haproxy.config import HEALTH_CHECK

class BackendHelperTestCase(unittest.TestCase):
def test_get_backend_routes(self):
routes = {'HW': [{'container_name': 'HW_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.3'},
{'container_name': 'HW_2', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.2'}],
routes = {'HW': [{'container_name': 'HW_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.3', 'health_check': 'check'},
{'container_name': 'HW_2', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.2', 'health_check': 'check'}],
'WEB': [{'container_name': 'WEB_2', 'proto': 'tcp', 'port': '8080', 'addr': '10.7.0.4'},
{'container_name': 'WEB_1', 'proto': 'tcp', 'port': '8080', 'addr': '10.7.0.5'}]}
self.assertEqual(["server HW_1 10.7.0.3:80 check", "server HW_2 10.7.0.2:80 check"],
get_backend_routes(route_setting="check", is_sticky=False,
routes=routes, routes_added=[], service_alias="HW", details={}))
self.assertEqual(["server WEB_1 10.7.0.5:8080", "server WEB_2 10.7.0.4:8080"],
get_backend_routes(route_setting="", is_sticky=False,
routes=routes, routes_added=[], service_alias="WEB", details={}))
self.assertEqual(["server WEB_1 10.7.0.5:8080 cookie WEB_1", "server WEB_2 10.7.0.4:8080 cookie WEB_2"],
get_backend_routes(route_setting="", is_sticky=True,
routes=routes, routes_added=[], service_alias="WEB", details={}))
get_backend_routes(is_sticky=False, routes=routes, routes_added=[], service_alias="HW"))
self.assertEqual(["server WEB_1 10.7.0.5:8080 %s" % HEALTH_CHECK, "server WEB_2 10.7.0.4:8080 %s" % HEALTH_CHECK],
get_backend_routes(is_sticky=False, routes=routes, routes_added=[], service_alias="WEB"))
self.assertEqual(["server WEB_1 10.7.0.5:8080 cookie WEB_1 %s" % HEALTH_CHECK, "server WEB_2 10.7.0.4:8080 cookie WEB_2 %s" % HEALTH_CHECK],
get_backend_routes(is_sticky=True, routes=routes, routes_added=[], service_alias="WEB"))
self.assertEqual([],
get_backend_routes(route_setting="", is_sticky=False,
routes={}, routes_added=[], service_alias="WEB", details={}))
self.assertEqual(["server WEB_2 10.7.0.4:8080"],
get_backend_routes(route_setting="", is_sticky=False,
routes=routes, routes_added=[
get_backend_routes(is_sticky=False, routes={}, routes_added=[], service_alias="WEB"))
self.assertEqual(["server WEB_2 10.7.0.4:8080 %s" % HEALTH_CHECK],
get_backend_routes(is_sticky=False, routes=routes, routes_added=[
{'container_name': 'WEB_1', 'proto': 'tcp', 'port': '8080', 'addr': '10.7.0.5'}],
service_alias="WEB", details={}))
self.assertEqual(["server WEB_2 10.7.0.4:8080 cookie WEB_2"],
get_backend_routes(route_setting="", is_sticky=True,
routes=routes, routes_added=[
service_alias="WEB"))
self.assertEqual(["server WEB_2 10.7.0.4:8080 cookie WEB_2 %s" % HEALTH_CHECK],
get_backend_routes(is_sticky=True, routes=routes, routes_added=[
{'container_name': 'WEB_1', 'proto': 'tcp', 'port': '8080', 'addr': '10.7.0.5'}],
service_alias="WEB", details={}))
self.assertEqual(["server WEB_1 10.7.0.5:8080", "server WEB_2 10.7.0.4:8080"],
get_backend_routes(route_setting="", is_sticky=False,
routes=routes, routes_added=[
service_alias="WEB"))
self.assertEqual(["server WEB_1 10.7.0.5:8080 %s" % HEALTH_CHECK, "server WEB_2 10.7.0.4:8080 %s" % HEALTH_CHECK],
get_backend_routes(is_sticky=False, routes=routes, routes_added=[
{'container_name': 'WEB_3', 'proto': 'tcp', 'port': '8080', 'addr': '10.7.0.5'}],
service_alias="WEB", details={}))
service_alias="WEB"))
self.assertEqual([],
get_backend_routes(route_setting="", is_sticky=False,
routes=routes, routes_added=[
get_backend_routes(is_sticky=False, routes=routes, routes_added=[
{'container_name': 'WEB_2', 'proto': 'tcp', 'port': '8080', 'addr': '10.7.0.4'},
{'container_name': 'WEB_1', 'proto': 'tcp', 'port': '8080', 'addr': '10.7.0.5'}],
service_alias="WEB", details={}))
service_alias="WEB"))
self.assertEqual(["server HW_1 10.7.0.3:80 check", "server HW_2 10.7.0.2:80 check"],
get_backend_routes(route_setting="check", is_sticky=False,
routes=routes, routes_added=[
get_backend_routes(is_sticky=False, routes=routes, routes_added=[
{'container_name': 'WEB_3', 'proto': 'tcp', 'port': '8080', 'addr': '10.7.0.5'}],
service_alias="HW", details={}))
service_alias="HW"))
self.assertEqual([],
get_backend_routes(route_setting="", is_sticky=False,
routes=routes, routes_added=[], service_alias="HELLO", details={}))

def test_get_backend_routes_with_failover(self):
routes = {'HW': [{'container_name': 'HW_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.3'},
{'container_name': 'HW_2', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.2'}],
'WEB': [{'container_name': 'WEB_2', 'proto': 'tcp', 'port': '8080', 'addr': '10.7.0.4'},
{'container_name': 'WEB_1', 'proto': 'tcp', 'port': '8080', 'addr': '10.7.0.5'}]}
details = {'HW': {'failover': "true"},
'WEB': {'failover': ""}}

self.assertEqual(["server HW_1 10.7.0.3:80 check backup", "server HW_2 10.7.0.2:80 check backup"],
get_backend_routes(route_setting="check", is_sticky=False,
routes=routes, routes_added=[
{'container_name': 'WEB_3', 'proto': 'tcp', 'port': '8080', 'addr': '10.7.0.5'}],
service_alias="HW", details=details))
self.assertEqual(["server WEB_1 10.7.0.5:8080", "server WEB_2 10.7.0.4:8080"],
get_backend_routes(route_setting="", is_sticky=False,
routes=routes, routes_added=[], service_alias="WEB", details=details))

def test_get_route_health(self):
details = {'web-a': {'health_check': 'health_check_web_a'},
'web-b': {'health_check': ''},
'web-c': {}}
default_health_check = 'default_health_check'

self.assertEqual("health_check_web_a", get_route_health_check(details, 'web-a', default_health_check))
self.assertEqual(default_health_check, get_route_health_check(details, 'web-b', default_health_check))
self.assertEqual(default_health_check, get_route_health_check(details, 'web-c', default_health_check))
self.assertEqual(default_health_check, get_route_health_check(details, 'web-d', default_health_check))

def test_get_extra_route_settings(self):
details = {'web-a': {'extra_route_settings': 'extra_route_settings_web_a'},
'web-b': {'extra_route_settings': ''},
'web-c': {}}
default_route_settings = 'default_routsettings'

self.assertEqual("extra_route_settings_web_a",
get_extra_route_settings(details, 'web-a', default_route_settings))
self.assertEqual(default_route_settings, get_extra_route_settings(details, 'web-b', default_route_settings))
self.assertEqual(default_route_settings, get_extra_route_settings(details, 'web-c', default_route_settings))
self.assertEqual(default_route_settings, get_extra_route_settings(details, 'web-d', default_route_settings))
get_backend_routes(is_sticky=False, routes=routes, routes_added=[], service_alias="HELLO"))

def test_get_websocket_setting(self):
vhosts = [{'service_alias': 'web-a', 'path': '', 'host': 'a.com', 'scheme': 'http', 'port': '8080'},
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/parser/test_legacy_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def test_parse_routes(self):
}

routes = {'WORLD': [{'container_name': 'WORLD_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.3'}],
'HELLO': [{'container_name': 'HELLO_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.1', }],
'HELLO': [{'container_name': 'HELLO_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.1'}],
'DUPLICATED': [{'container_name': 'DUPLICATED', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.1'}]}
self.assertEqual(routes, specs._parse_routes(details, envvars))

Expand Down
Loading