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

Commit a37529e

Browse files
committed
reload haproxy when scale a additional service on compose v2
1 parent 42672c5 commit a37529e

7 files changed

Lines changed: 53 additions & 44 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ Settings in this part is immutable, you have to redeploy HAProxy service to make
166166

167167
|Environment Variable|Default|Description|
168168
|:-----:|:-----:|:----------|
169-
|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 accessible to this containers.|
169+
|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.|
170170
|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)|
171171
|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`|
172172
|CA_CERT| |CA cert for haproxy to verify the client. Use the same format as `DEFAULT_SSL_CERT`|

haproxy/eventhandler.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import json
22
import logging
33
import time
4+
import os
45

56
import dockercloud
67
from compose.cli.docker_client import docker_client
@@ -26,7 +27,7 @@ def on_cloud_event(message):
2627
# When service scale up/down or container start/stop/terminate/redeploy, reload the service
2728
if event.get("state", "") not in ["In progress", "Pending", "Terminating", "Starting", "Scaling", "Stopping"] and \
2829
event.get("type", "").lower() in ["container", "service"] and \
29-
len(set(Haproxy.cls_linked_services).intersection(set(event.get("parents", [])))) > 0:
30+
len(Haproxy.cls_linked_services.intersection(set(event.get("parents", [])))) > 0:
3031
msg = "Docker Cloud Event: %s %s is %s" % (
3132
event["type"], get_uuid_from_resource_uri(event.get("resource_uri", "")), event["state"].lower())
3233
run_haproxy(msg)
@@ -74,7 +75,12 @@ def listen_dockercloud_events():
7475

7576
def listen_docker_events():
7677
try:
77-
docker = docker_client()
78+
79+
try:
80+
docker = docker_client()
81+
except:
82+
docker = docker_client(os.environ)
83+
7884
docker.ping()
7985
for event in docker.events(decode=True):
8086
logger.debug(event)

haproxy/haproxycfg.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def run_haproxy(msg=None):
2626

2727

2828
class Haproxy(object):
29-
cls_linked_services = []
29+
cls_linked_services = set()
3030
cls_cfg = None
3131
cls_process = None
3232
cls_certs = []
@@ -77,23 +77,24 @@ def _init_cloud_links():
7777
@staticmethod
7878
def _init_new_links():
7979
try:
80-
docker = docker_client()
80+
try:
81+
docker = docker_client()
82+
except:
83+
docker = docker_client(os.environ)
84+
8185
docker.ping()
8286
container_id = os.environ.get("HOSTNAME", "")
8387
haproxy_container = docker.inspect_container(container_id)
8488
except Exception as e:
85-
logger.info("Docker API error, regressing to legacy links mode: ", e)
89+
logger.info("Docker API error, regressing to legacy links mode: %s" % e)
8690
return None
8791
links, Haproxy.cls_linked_services = NewLinkHelper.get_new_links(docker, haproxy_container)
8892

89-
try:
90-
if ADDITIONAL_SERVICES:
91-
additional_services = ADDITIONAL_SERVICES.split(",")
92-
NewLinkHelper.get_additional_links(docker, additional_services, haproxy_container,
93-
links, Haproxy.cls_linked_services)
94-
except Exception as e:
95-
logger.info("Error loading ADDITIONAL_SERVICES: %s" % str(e))
96-
return None
93+
if ADDITIONAL_SERVICES:
94+
additional_links, additional_services= NewLinkHelper.get_additional_links(docker, ADDITIONAL_SERVICES)
95+
if additional_links and additional_services:
96+
links.update(additional_links)
97+
Haproxy.cls_linked_services.update(additional_services)
9798

9899
logger.info("Linked service: %s", ", ".join(NewLinkHelper.get_service_links_str(links)))
99100
logger.info("Linked container: %s", ", ".join(NewLinkHelper.get_container_links_str(links)))

haproxy/helper/new_link_helper.py

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,24 @@ def get_new_links(docker, haproxy_container):
1313
linked_compose_services = _get_linked_compose_services(networks, project)
1414

1515
links = _calc_links(docker, linked_compose_services, project)
16-
return links, ["%s_%s" % (project, service) for service in linked_compose_services]
16+
return links, set(["%s_%s" % (project, service) for service in linked_compose_services])
1717

1818

19-
def get_additional_links(docker, additional_services, haproxy_container, links, linked_services):
20-
networks_data = docker.networks()
21-
haproxy_networks_ids = _find_container_networks_ids(haproxy_container, networks_data)
22-
for _container in docker.containers():
23-
container_id = _container.get("Id", "")
24-
container = docker.inspect_container(container_id)
25-
compose_project = container.get("Config", {}).get("Labels", {}).get("com.docker.compose.project", "")
26-
compose_service = container.get("Config", {}).get("Labels", {}).get("com.docker.compose.service", "")
27-
for _service in additional_services:
28-
terms = _service.strip().split(":")
19+
def get_additional_links(docker, additional_services):
20+
links = {}
21+
services = set()
22+
for additional_service in additional_services.split(","):
23+
terms = additional_service.strip().split(":")
2924
if len(terms) == 2:
30-
if terms[0].strip() == compose_project and terms[1].strip() == compose_service:
31-
container_networks_ids = _find_container_networks_ids(container, networks_data)
32-
if set(container_networks_ids).intersection(haproxy_networks_ids):
33-
if _service not in linked_services:
34-
linked_services.append(_service)
35-
container_name = container.get("Name").lstrip("/")
36-
container_evvvars = _get_container_envvars(container)
37-
endpoints = _get_container_endpoints(container, container_name)
38-
links[container_id] = {"service_name": _service,
39-
"container_envvars": container_evvvars,
40-
"container_name": container_name,
41-
"endpoints": endpoints,
42-
"compose_service": compose_service,
43-
"compose_project": compose_project}
44-
else:
45-
logger.info("Ignoring container '%s': no shared network with haproxy")
25+
project = terms[0]
26+
service = terms[1]
27+
link = _calc_links(docker, [service], project)
28+
if link:
29+
links.update(link)
30+
services.add("%s_%s" % (project, service))
31+
else:
32+
logger.info("Cannot find the additional service: %s" % additional_service.strip())
33+
return links, services
4634

4735

4836
def _find_container_networks_ids(container, networks_data):

haproxy/main.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ def check_link_mode(container_uri, service_uri, api_auth):
6868
link_mode = "new"
6969
reason = ""
7070
try:
71-
docker = docker_client()
71+
try:
72+
docker = docker_client()
73+
except:
74+
docker = docker_client(os.environ)
7275
docker.ping()
7376
except Exception as e:
7477
reason = "unable to connect to docker daemon %s" % e

tests/unit/helper/test_new_link_helper.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import unittest
22

33
from haproxy.helper.new_link_helper import _calc_links, _get_linked_compose_services, _get_container_envvars, \
4-
_get_container_endpoints, get_container_links_str, get_service_links_str
4+
_get_container_endpoints, get_container_links_str, get_service_links_str, get_additional_links
55

66
container1 = {u'ExecIDs': None,
77
u'State': {u'Status': u'running', u'Pid': 28121, u'OOMKilled': False, u'Dead': False, u'Paused': False,
@@ -324,6 +324,17 @@ def test_calc_links(self):
324324
docker = self.Docker()
325325
self.assertEqual(links, _calc_links(docker, ['hello', 'world'], 'tmp'))
326326

327+
def test_get_additional_links(self):
328+
docker = self.Docker()
329+
330+
additional_links, additional_services = get_additional_links(docker, "tmp:hello, tmp:world")
331+
self.assertEqual(links, additional_links)
332+
self.assertEqual(set(["tmp_hello","tmp_world"]), additional_services)
333+
334+
additional_links, additional_services = get_additional_links(docker, "tmp:hello, tmp:world, tmp:aaa, aaa:bbb")
335+
self.assertEqual(links, additional_links)
336+
self.assertSetEqual(set(["tmp_hello", "tmp_world"]), additional_services)
337+
327338
def test_get_container_endpoints(self):
328339
endpoints = {u'1936/tcp': u'tcp://tmp_lb_1:1936', u'443/tcp': u'tcp://tmp_lb_1:443',
329340
u'80/tcp': u'tcp://tmp_lb_1:80'}

tests/unit/test_eventhandler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
class OnCloudEventTestCase(unittest.TestCase):
1414
def setUp(self):
1515
self.linked_services = Haproxy.cls_linked_services
16-
Haproxy.cls_linked_services = ["/svc/a/", "/svc/b/", "/svc/c/"]
16+
Haproxy.cls_linked_services = set(["/svc/a/", "/svc/b/", "/svc/c/"])
1717
self.service_uri = config.HAPROXY_SERVICE_URI
1818
config.HAPROXY_SERVICE_URI = "/svc/uuid/"
1919

0 commit comments

Comments
 (0)