From 1791465f0998acf2863bd39476581c800041006c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=A6ksvang=20=C3=98stergaard?= Date: Wed, 23 Aug 2017 10:09:32 +0200 Subject: [PATCH 1/5] Make route settings local per route --- haproxy/helper/backend_helper.py | 28 +++++----------------------- haproxy/parser/legacy_parser.py | 13 +++++++++++++ haproxy/parser/new_parser.py | 12 +++++++++++- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/haproxy/helper/backend_helper.py b/haproxy/helper/backend_helper.py index 221659d..64029cd 100644 --- a/haproxy/helper/backend_helper.py +++ b/haproxy/helper/backend_helper.py @@ -1,6 +1,6 @@ import re -from haproxy.config import HEALTH_CHECK, HTTP_BASIC_AUTH, EXTRA_ROUTE_SETTINGS +from haproxy.config import HTTP_BASIC_AUTH from haproxy.utils import get_service_attribute @@ -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: @@ -38,29 +35,14 @@ 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 details.get(service_alias, {}).get('failover', False): - backend_route.append("backup") + if "route_settings" in route and route["route_settings"]: + backend_route.append(route["route_settings"]) backend_routes.append(" ".join(backend_route)) 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: diff --git a/haproxy/parser/legacy_parser.py b/haproxy/parser/legacy_parser.py index 9080779..1fd36f7 100644 --- a/haproxy/parser/legacy_parser.py +++ b/haproxy/parser/legacy_parser.py @@ -1,6 +1,7 @@ import os import haproxy.config +from haproxy.config import HEALTH_CHECK from haproxy.parser.base_parser import EnvParser, Specs @@ -64,6 +65,18 @@ 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 not route_health_check: + route_health_check = HEALTH_CHECK + extra_route_settings = details.get(service_alias, {}).get("extra_route_settings") + if not extra_route_settings: + extra_route_settings = "" + if details.get(service_alias, {}).get("failover"): + extra_route_settings = " ".join([extra_route_settings, "backup"]).strip() + route_settings = " ".join([route_health_check, extra_route_settings]).strip() + route.update({"route_settings": 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: diff --git a/haproxy/parser/new_parser.py b/haproxy/parser/new_parser.py index 9804645..4e8d90b 100644 --- a/haproxy/parser/new_parser.py +++ b/haproxy/parser/new_parser.py @@ -1,6 +1,6 @@ import haproxy.config from haproxy.parser.base_parser import Specs, EnvParser - +from haproxy.config import HEALTH_CHECK class NewSpecs(Specs): def __init__(self, links): @@ -39,6 +39,16 @@ 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 not route_health_check: + route_health_check = HEALTH_CHECK + extra_route_settings = details.get(service_alias, {}).get("extra_route_settings") + if not extra_route_settings: + extra_route_settings = "" + if details.get(service_alias, {}).get("failover"): + extra_route_settings = " ".join([extra_route_settings, "backup"]).strip() + route_settings = " ".join([route_health_check, extra_route_settings]).strip() + route.update({"route_settings": 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]: From aaa9a90fbbb18bb64c07507944448d856fe0e5eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=A6ksvang=20=C3=98stergaard?= Date: Wed, 23 Aug 2017 10:10:00 +0200 Subject: [PATCH 2/5] Fix tests --- tests/unit/helper/test_backend_helper.py | 84 +++++------------------- tests/unit/parser/test_legacy_parser.py | 11 ++-- tests/unit/parser/test_new_parser.py | 33 +++++----- tests/unit/test_haproxycfg.py | 20 +++--- 4 files changed, 49 insertions(+), 99 deletions(-) diff --git a/tests/unit/helper/test_backend_helper.py b/tests/unit/helper/test_backend_helper.py index 8dafaa8..009a54b 100644 --- a/tests/unit/helper/test_backend_helper.py +++ b/tests/unit/helper/test_backend_helper.py @@ -5,91 +5,41 @@ 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', 'route_settings': 'check'}, + {'container_name': 'HW_2', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.2', 'route_settings': '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={})) + get_backend_routes(is_sticky=False, routes=routes, routes_added=[], service_alias="HW")) 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={})) + 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", "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=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={})) + get_backend_routes(is_sticky=False, routes={}, routes_added=[], service_alias="WEB")) 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, routes_added=[ {'container_name': 'WEB_1', 'proto': 'tcp', 'port': '8080', 'addr': '10.7.0.5'}], - service_alias="WEB", details={})) + service_alias="WEB")) 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=[ + 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={})) + service_alias="WEB")) 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=[ + 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'}, diff --git a/tests/unit/parser/test_legacy_parser.py b/tests/unit/parser/test_legacy_parser.py index cf30508..152bd37 100644 --- a/tests/unit/parser/test_legacy_parser.py +++ b/tests/unit/parser/test_legacy_parser.py @@ -1,6 +1,7 @@ import unittest from haproxy.parser.legacy_parser import * +from haproxy.config import HEALTH_CHECK class SpecsTestCase(unittest.TestCase): @@ -24,8 +25,8 @@ def setUp(self): 'tcp_ports': [], 'balance': None, 'extra_settings': None, 'option': [], "extra_route_settings": None, "failover": None, 'exclude_basic_auth': None}} - 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'}]} + self.routes = {'WORLD': [{'container_name': 'WORLD_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.3', 'route_settings': HEALTH_CHECK}], + 'HELLO': [{'container_name': 'HELLO_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.1', 'route_settings': HEALTH_CHECK}]} self.vhosts = [{'path': '', 'host': 'a.com', 'scheme': 'http', 'port': '80', 'service_alias': 'WORLD'}, {'path': '', 'host': 'b.com', 'scheme': 'http', 'port': '80', 'service_alias': 'HELLO'}] @@ -119,9 +120,9 @@ def test_parse_routes(self): 'option': [], "extra_route_settings": None, 'exclude_basic_auth': None} } - 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', }], - 'DUPLICATED': [{'container_name': 'DUPLICATED', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.1'}]} + routes = {'WORLD': [{'container_name': 'WORLD_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.3', 'route_settings': HEALTH_CHECK}], + 'HELLO': [{'container_name': 'HELLO_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.1', 'route_settings': HEALTH_CHECK}], + 'DUPLICATED': [{'container_name': 'DUPLICATED', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.1', 'route_settings': HEALTH_CHECK}]} self.assertEqual(routes, specs._parse_routes(details, envvars)) diff --git a/tests/unit/parser/test_new_parser.py b/tests/unit/parser/test_new_parser.py index 1e50888..9cab50a 100644 --- a/tests/unit/parser/test_new_parser.py +++ b/tests/unit/parser/test_new_parser.py @@ -1,6 +1,7 @@ import unittest from haproxy.parser.new_parser import * +from haproxy.config import HEALTH_CHECK class SpecsTestCase(unittest.TestCase): @@ -46,11 +47,13 @@ def setUp(self): self.routes = {'tmp_hello': [{'addr': 'tmp_hello_1', 'container_name': 'tmp_hello_1', 'port': '80', - 'proto': 'tcp'}], + 'proto': 'tcp', + 'route_settings': HEALTH_CHECK}], 'tmp_world': [{'addr': 'tmp_world_1', 'container_name': 'tmp_world_1', 'port': '80', - 'proto': 'tcp'}]} + 'proto': 'tcp', + 'route_settings': HEALTH_CHECK}]} self.links2 = {'id1': {'service_name': 'tmp_world', 'container_name': 'tmp_world_1', 'endpoints': { @@ -71,12 +74,12 @@ def setUp(self): }, } self.routes2 = { - 'tmp_world': [{'container_name': 'tmp_world_2', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_2'}, - {'container_name': 'tmp_world_2', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_world_2'}, - {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_1'}, - {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_world_1'}], - 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1'}, - {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_hello_1'}]} + 'tmp_world': [{'container_name': 'tmp_world_2', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_2', 'route_settings': HEALTH_CHECK}, + {'container_name': 'tmp_world_2', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_world_2', 'route_settings': HEALTH_CHECK}, + {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_1', 'route_settings': HEALTH_CHECK}, + {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_world_1', 'route_settings': HEALTH_CHECK}], + 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}, + {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}]} def test_parse_service_aliases(self): self.assertEqual([], NewSpecs._parse_service_aliases({})) @@ -115,19 +118,19 @@ def test_parse_routes_with_exclude_ports(self): self.assertEqual(self.routes2, NewSpecs._parse_routes(details, self.links2)) details = {'tmp_world': {'exclude_ports': ['80']}} - routes = {'tmp_world': [{'container_name': 'tmp_world_2', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_2'}, - {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_1'}], - 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1'}, - {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_hello_1'}]} + routes = {'tmp_world': [{'container_name': 'tmp_world_2', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_2', 'route_settings': HEALTH_CHECK}, + {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_1', 'route_settings': HEALTH_CHECK}], + 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}, + {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}]} self.assertEqual(routes, NewSpecs._parse_routes(details, self.links2)) details = {'tmp_world': {'exclude_ports': ['80', '22']}} routes = {'tmp_world': [], - 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1'}, - {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_hello_1'}]} + 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}, + {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}]} self.assertEqual(routes, NewSpecs._parse_routes(details, self.links2)) details = {'tmp_world': {'exclude_ports': ['80', '22']}, 'tmp_hello': {'exclude_ports': ['80']}} routes = {'tmp_world': [], - 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1'}]} + 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}]} self.assertEqual(routes, NewSpecs._parse_routes(details, self.links2)) diff --git a/tests/unit/test_haproxycfg.py b/tests/unit/test_haproxycfg.py index 16a95c8..28ffc26 100644 --- a/tests/unit/test_haproxycfg.py +++ b/tests/unit/test_haproxycfg.py @@ -319,13 +319,11 @@ def test_config_backend_sections(self, mock_init, mock_details, mock_services, m haproxy = Haproxy() haproxy.specs = Specs() mock_details.return_value = {'HW': {'balance': "source", - 'virtual_host': "a.com", - 'health_check': "check", - 'extra_route_settings': 'extra settings'}} + 'virtual_host': "a.com"}} mock_services.return_value = ["HW"] mock_routes.return_value = { - 'HW': [{'container_name': 'HW_1', 'proto': 'http', 'port': '80', 'addr': '10.7.0.2'}, - {'container_name': 'HW_2', 'proto': 'http', 'port': '80', 'addr': '10.7.0.3'}]} + 'HW': [{'container_name': 'HW_1', 'proto': 'http', 'port': '80', 'addr': '10.7.0.2', 'route_settings': 'check extra settings'}, + {'container_name': 'HW_2', 'proto': 'http', 'port': '80', 'addr': '10.7.0.3', 'route_settings': 'check extra settings'}]} mock_vhosts.return_value = [ {'service_alias': 'HW', 'path': '', 'host': 'a.com', 'scheme': 'http', 'port': '80'}] self.assertEqual(OrderedDict([('backend SERVICE_HW', ['balance source', @@ -335,11 +333,10 @@ def test_config_backend_sections(self, mock_init, mock_details, mock_services, m haproxy = Haproxy() haproxy.specs = Specs() - mock_details.return_value = {'HW': {'balance': "source", - 'health_check': "check"}} + mock_details.return_value = {'HW': {'balance': "source"}} mock_services.return_value = ["HW"] mock_routes.return_value = { - 'HW': [{'container_name': 'HW_1', 'proto': 'http', 'port': '80', 'addr': '10.7.0.2'}, + 'HW': [{'container_name': 'HW_1', 'proto': 'http', 'port': '80', 'addr': '10.7.0.2', 'route_settings': 'check'}, {'container_name': 'HW_2', 'proto': 'http', 'port': '80', 'addr': '10.7.0.3'}]} mock_vhosts.return_value = [] self.assertEqual({}, haproxy._config_backend_sections()) @@ -347,12 +344,11 @@ def test_config_backend_sections(self, mock_init, mock_details, mock_services, m haproxy = Haproxy() haproxy.specs = Specs() haproxy.require_default_route = True - mock_details.return_value = {'HW': {'balance': "source", - 'health_check': "check"}} + mock_details.return_value = {'HW': {'balance': "source"}} mock_services.return_value = ["HW"] mock_routes.return_value = { - 'HW': [{'container_name': 'HW_1', 'proto': 'http', 'port': '80', 'addr': '10.7.0.2'}, - {'container_name': 'HW_2', 'proto': 'http', 'port': '80', 'addr': '10.7.0.3'}]} + 'HW': [{'container_name': 'HW_1', 'proto': 'http', 'port': '80', 'addr': '10.7.0.2', 'route_settings': 'check'}, + {'container_name': 'HW_2', 'proto': 'http', 'port': '80', 'addr': '10.7.0.3', 'route_settings': 'check'}]} mock_vhosts.return_value = [] self.assertEqual(OrderedDict([('backend default_service', ['balance source', 'server HW_1 10.7.0.2:80 check', From f31f1f1eae2bacda5c29b34411e4b85435219dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=A6ksvang=20=C3=98stergaard?= Date: Wed, 23 Aug 2017 10:10:09 +0200 Subject: [PATCH 3/5] Updated readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 115bb93..767f96a 100644 --- a/README.md +++ b/README.md @@ -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, 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. From 860c58329c9011cbc20d8a7b4bad3f8cd661d30b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=A6ksvang=20=C3=98stergaard?= Date: Wed, 23 Aug 2017 10:53:38 +0200 Subject: [PATCH 4/5] Separate extra route settings and health check --- haproxy/helper/backend_helper.py | 11 +++++--- haproxy/parser/legacy_parser.py | 20 +++++++------- haproxy/parser/new_parser.py | 20 +++++++------- tests/unit/helper/test_backend_helper.py | 16 ++++++------ tests/unit/parser/test_legacy_parser.py | 11 ++++---- tests/unit/parser/test_new_parser.py | 33 +++++++++++------------- tests/unit/test_haproxycfg.py | 10 +++---- 7 files changed, 62 insertions(+), 59 deletions(-) diff --git a/haproxy/helper/backend_helper.py b/haproxy/helper/backend_helper.py index 64029cd..74f08fa 100644 --- a/haproxy/helper/backend_helper.py +++ b/haproxy/helper/backend_helper.py @@ -1,6 +1,6 @@ import re -from haproxy.config import HTTP_BASIC_AUTH +from haproxy.config import HTTP_BASIC_AUTH, HEALTH_CHECK from haproxy.utils import get_service_attribute @@ -35,8 +35,13 @@ def get_backend_routes(is_sticky, routes, routes_added, service_alias): if is_sticky: backend_route.append("cookie %s" % route["container_name"]) - if "route_settings" in route and route["route_settings"]: - backend_route.append(route["route_settings"]) + if "health_check" in route and route["health_check"]: + backend_route.append(route["health_check"]) + else: + backend_route.append(HEALTH_CHECK) + + if "extra_route_settings" in route and route["extra_route_settings"]: + backend_route.append(route["extra_route_settings"]) backend_routes.append(" ".join(backend_route)) diff --git a/haproxy/parser/legacy_parser.py b/haproxy/parser/legacy_parser.py index 1fd36f7..e9f4080 100644 --- a/haproxy/parser/legacy_parser.py +++ b/haproxy/parser/legacy_parser.py @@ -1,7 +1,6 @@ import os import haproxy.config -from haproxy.config import HEALTH_CHECK from haproxy.parser.base_parser import EnvParser, Specs @@ -67,15 +66,18 @@ def _parse_routes(details, envvars): route.update({"container_name": container_name}) route_health_check = details.get(service_alias, {}).get("health_check") - if not route_health_check: - route_health_check = HEALTH_CHECK - extra_route_settings = details.get(service_alias, {}).get("extra_route_settings") - if not extra_route_settings: - extra_route_settings = "" + if route_health_check: + route.update({"health_check": route_health_check}) + + failover = None if details.get(service_alias, {}).get("failover"): - extra_route_settings = " ".join([extra_route_settings, "backup"]).strip() - route_settings = " ".join([route_health_check, extra_route_settings]).strip() - route.update({"route_settings": route_settings}) + 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): diff --git a/haproxy/parser/new_parser.py b/haproxy/parser/new_parser.py index 4e8d90b..49a3b49 100644 --- a/haproxy/parser/new_parser.py +++ b/haproxy/parser/new_parser.py @@ -1,6 +1,5 @@ import haproxy.config from haproxy.parser.base_parser import Specs, EnvParser -from haproxy.config import HEALTH_CHECK class NewSpecs(Specs): def __init__(self, links): @@ -39,16 +38,17 @@ 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 not route_health_check: - route_health_check = HEALTH_CHECK - extra_route_settings = details.get(service_alias, {}).get("extra_route_settings") - if not extra_route_settings: - extra_route_settings = "" + + failover = None if details.get(service_alias, {}).get("failover"): - extra_route_settings = " ".join([extra_route_settings, "backup"]).strip() - route_settings = " ".join([route_health_check, extra_route_settings]).strip() - route.update({"route_settings": route_settings}) + 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]: diff --git a/tests/unit/helper/test_backend_helper.py b/tests/unit/helper/test_backend_helper.py index 009a54b..9dec20b 100644 --- a/tests/unit/helper/test_backend_helper.py +++ b/tests/unit/helper/test_backend_helper.py @@ -1,31 +1,31 @@ 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', 'route_settings': 'check'}, - {'container_name': 'HW_2', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.2', 'route_settings': 'check'}], + 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(is_sticky=False, routes=routes, routes_added=[], service_alias="HW")) - self.assertEqual(["server WEB_1 10.7.0.5:8080", "server WEB_2 10.7.0.4:8080"], + 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", "server WEB_2 10.7.0.4:8080 cookie WEB_2"], + 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(is_sticky=False, routes={}, routes_added=[], service_alias="WEB")) - self.assertEqual(["server WEB_2 10.7.0.4:8080"], + 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")) - self.assertEqual(["server WEB_2 10.7.0.4:8080 cookie WEB_2"], + 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")) - self.assertEqual(["server WEB_1 10.7.0.5:8080", "server WEB_2 10.7.0.4:8080"], + 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")) diff --git a/tests/unit/parser/test_legacy_parser.py b/tests/unit/parser/test_legacy_parser.py index 152bd37..8958e48 100644 --- a/tests/unit/parser/test_legacy_parser.py +++ b/tests/unit/parser/test_legacy_parser.py @@ -1,7 +1,6 @@ import unittest from haproxy.parser.legacy_parser import * -from haproxy.config import HEALTH_CHECK class SpecsTestCase(unittest.TestCase): @@ -25,8 +24,8 @@ def setUp(self): 'tcp_ports': [], 'balance': None, 'extra_settings': None, 'option': [], "extra_route_settings": None, "failover": None, 'exclude_basic_auth': None}} - self.routes = {'WORLD': [{'container_name': 'WORLD_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.3', 'route_settings': HEALTH_CHECK}], - 'HELLO': [{'container_name': 'HELLO_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.1', 'route_settings': HEALTH_CHECK}]} + 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'}]} self.vhosts = [{'path': '', 'host': 'a.com', 'scheme': 'http', 'port': '80', 'service_alias': 'WORLD'}, {'path': '', 'host': 'b.com', 'scheme': 'http', 'port': '80', 'service_alias': 'HELLO'}] @@ -120,9 +119,9 @@ def test_parse_routes(self): 'option': [], "extra_route_settings": None, 'exclude_basic_auth': None} } - routes = {'WORLD': [{'container_name': 'WORLD_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.3', 'route_settings': HEALTH_CHECK}], - 'HELLO': [{'container_name': 'HELLO_1', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.1', 'route_settings': HEALTH_CHECK}], - 'DUPLICATED': [{'container_name': 'DUPLICATED', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.1', 'route_settings': HEALTH_CHECK}]} + 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'}], + 'DUPLICATED': [{'container_name': 'DUPLICATED', 'proto': 'tcp', 'port': '80', 'addr': '10.7.0.1'}]} self.assertEqual(routes, specs._parse_routes(details, envvars)) diff --git a/tests/unit/parser/test_new_parser.py b/tests/unit/parser/test_new_parser.py index 9cab50a..1e50888 100644 --- a/tests/unit/parser/test_new_parser.py +++ b/tests/unit/parser/test_new_parser.py @@ -1,7 +1,6 @@ import unittest from haproxy.parser.new_parser import * -from haproxy.config import HEALTH_CHECK class SpecsTestCase(unittest.TestCase): @@ -47,13 +46,11 @@ def setUp(self): self.routes = {'tmp_hello': [{'addr': 'tmp_hello_1', 'container_name': 'tmp_hello_1', 'port': '80', - 'proto': 'tcp', - 'route_settings': HEALTH_CHECK}], + 'proto': 'tcp'}], 'tmp_world': [{'addr': 'tmp_world_1', 'container_name': 'tmp_world_1', 'port': '80', - 'proto': 'tcp', - 'route_settings': HEALTH_CHECK}]} + 'proto': 'tcp'}]} self.links2 = {'id1': {'service_name': 'tmp_world', 'container_name': 'tmp_world_1', 'endpoints': { @@ -74,12 +71,12 @@ def setUp(self): }, } self.routes2 = { - 'tmp_world': [{'container_name': 'tmp_world_2', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_2', 'route_settings': HEALTH_CHECK}, - {'container_name': 'tmp_world_2', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_world_2', 'route_settings': HEALTH_CHECK}, - {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_1', 'route_settings': HEALTH_CHECK}, - {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_world_1', 'route_settings': HEALTH_CHECK}], - 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}, - {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}]} + 'tmp_world': [{'container_name': 'tmp_world_2', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_2'}, + {'container_name': 'tmp_world_2', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_world_2'}, + {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_1'}, + {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_world_1'}], + 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1'}, + {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_hello_1'}]} def test_parse_service_aliases(self): self.assertEqual([], NewSpecs._parse_service_aliases({})) @@ -118,19 +115,19 @@ def test_parse_routes_with_exclude_ports(self): self.assertEqual(self.routes2, NewSpecs._parse_routes(details, self.links2)) details = {'tmp_world': {'exclude_ports': ['80']}} - routes = {'tmp_world': [{'container_name': 'tmp_world_2', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_2', 'route_settings': HEALTH_CHECK}, - {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_1', 'route_settings': HEALTH_CHECK}], - 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}, - {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}]} + routes = {'tmp_world': [{'container_name': 'tmp_world_2', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_2'}, + {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_world_1'}], + 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1'}, + {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_hello_1'}]} self.assertEqual(routes, NewSpecs._parse_routes(details, self.links2)) details = {'tmp_world': {'exclude_ports': ['80', '22']}} routes = {'tmp_world': [], - 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}, - {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}]} + 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1'}, + {'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '80', 'addr': 'tmp_hello_1'}]} self.assertEqual(routes, NewSpecs._parse_routes(details, self.links2)) details = {'tmp_world': {'exclude_ports': ['80', '22']}, 'tmp_hello': {'exclude_ports': ['80']}} routes = {'tmp_world': [], - 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1', 'route_settings': HEALTH_CHECK}]} + 'tmp_hello': [{'container_name': 'tmp_world_1', 'proto': 'tcp', 'port': '22', 'addr': 'tmp_hello_1'}]} self.assertEqual(routes, NewSpecs._parse_routes(details, self.links2)) diff --git a/tests/unit/test_haproxycfg.py b/tests/unit/test_haproxycfg.py index 28ffc26..48476e3 100644 --- a/tests/unit/test_haproxycfg.py +++ b/tests/unit/test_haproxycfg.py @@ -322,8 +322,8 @@ def test_config_backend_sections(self, mock_init, mock_details, mock_services, m 'virtual_host': "a.com"}} mock_services.return_value = ["HW"] mock_routes.return_value = { - 'HW': [{'container_name': 'HW_1', 'proto': 'http', 'port': '80', 'addr': '10.7.0.2', 'route_settings': 'check extra settings'}, - {'container_name': 'HW_2', 'proto': 'http', 'port': '80', 'addr': '10.7.0.3', 'route_settings': 'check extra settings'}]} + 'HW': [{'container_name': 'HW_1', 'proto': 'http', 'port': '80', 'addr': '10.7.0.2', 'health_check': 'check', 'extra_route_settings': 'extra settings'}, + {'container_name': 'HW_2', 'proto': 'http', 'port': '80', 'addr': '10.7.0.3', 'health_check': 'check', 'extra_route_settings': 'extra settings'}]} mock_vhosts.return_value = [ {'service_alias': 'HW', 'path': '', 'host': 'a.com', 'scheme': 'http', 'port': '80'}] self.assertEqual(OrderedDict([('backend SERVICE_HW', ['balance source', @@ -336,7 +336,7 @@ def test_config_backend_sections(self, mock_init, mock_details, mock_services, m mock_details.return_value = {'HW': {'balance': "source"}} mock_services.return_value = ["HW"] mock_routes.return_value = { - 'HW': [{'container_name': 'HW_1', 'proto': 'http', 'port': '80', 'addr': '10.7.0.2', 'route_settings': 'check'}, + 'HW': [{'container_name': 'HW_1', 'proto': 'http', 'port': '80', 'addr': '10.7.0.2', 'health_check': 'check'}, {'container_name': 'HW_2', 'proto': 'http', 'port': '80', 'addr': '10.7.0.3'}]} mock_vhosts.return_value = [] self.assertEqual({}, haproxy._config_backend_sections()) @@ -347,8 +347,8 @@ def test_config_backend_sections(self, mock_init, mock_details, mock_services, m mock_details.return_value = {'HW': {'balance': "source"}} mock_services.return_value = ["HW"] mock_routes.return_value = { - 'HW': [{'container_name': 'HW_1', 'proto': 'http', 'port': '80', 'addr': '10.7.0.2', 'route_settings': 'check'}, - {'container_name': 'HW_2', 'proto': 'http', 'port': '80', 'addr': '10.7.0.3', 'route_settings': 'check'}]} + 'HW': [{'container_name': 'HW_1', 'proto': 'http', 'port': '80', 'addr': '10.7.0.2', 'health_check': 'check'}, + {'container_name': 'HW_2', 'proto': 'http', 'port': '80', 'addr': '10.7.0.3', 'health_check': 'check'}]} mock_vhosts.return_value = [] self.assertEqual(OrderedDict([('backend default_service', ['balance source', 'server HW_1 10.7.0.2:80 check', From b17bbe455c499194f8c2fc6f4b8a27dd6cba2096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=A6ksvang=20=C3=98stergaard?= Date: Wed, 23 Aug 2017 11:34:04 +0200 Subject: [PATCH 5/5] Bugfix and added default value for EXTRA_ROUTE_SETTINGS --- README.md | 2 +- haproxy/helper/backend_helper.py | 6 ++++-- haproxy/parser/new_parser.py | 5 +++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 767f96a..b502f65 100644 --- a/README.md +++ b/README.md @@ -248,7 +248,7 @@ 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, this service will run as a HAProxy `backup` for other configured service(s) in the same backend| +|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`| |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)| diff --git a/haproxy/helper/backend_helper.py b/haproxy/helper/backend_helper.py index 74f08fa..dcb9e05 100644 --- a/haproxy/helper/backend_helper.py +++ b/haproxy/helper/backend_helper.py @@ -1,6 +1,6 @@ import re -from haproxy.config import HTTP_BASIC_AUTH, HEALTH_CHECK +from haproxy.config import HEALTH_CHECK, HTTP_BASIC_AUTH, EXTRA_ROUTE_SETTINGS from haproxy.utils import get_service_attribute @@ -42,8 +42,10 @@ def get_backend_routes(is_sticky, routes, routes_added, service_alias): 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) diff --git a/haproxy/parser/new_parser.py b/haproxy/parser/new_parser.py index 49a3b49..e12c5c0 100644 --- a/haproxy/parser/new_parser.py +++ b/haproxy/parser/new_parser.py @@ -1,6 +1,7 @@ import haproxy.config from haproxy.parser.base_parser import Specs, EnvParser + class NewSpecs(Specs): def __init__(self, links): super(self.__class__, self).__init__() @@ -39,6 +40,10 @@ def _parse_routes(details, links): 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"