diff --git a/README.md b/README.md index 3bd5c73..ae1ef5a 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,7 @@ Settings in this part is immutable, you have to redeploy HAProxy service to make |STATS_AUTH|stats:stats|username and password required to access the Haproxy stats.| |STATS_PORT|1936|port for the HAProxy stats section. If this port is published, stats can be accessed at `http://:/` |TIMEOUT|connect 5000, client 50000, server 50000|comma-separated list of HAProxy `timeout` entries to the `default` section.| +|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.| ### Settings in linked application services### diff --git a/haproxy/haproxycfg.py b/haproxy/haproxycfg.py index 6a2c951..c6ef383 100644 --- a/haproxy/haproxycfg.py +++ b/haproxy/haproxycfg.py @@ -80,6 +80,17 @@ def _init_new_links(): logger.info("Docker API error, regressing to legacy links mode: ", e) return None links, Haproxy.cls_linked_services = NewLinkHelper.get_new_links(docker, haproxy_container) + + try: + additional_services_str = os.environ.get("ADDITIONAL_SERVICES", "") + if additional_services_str!="": + additional_services = additional_services_str.split(",") + NewLinkHelper.get_additional_links(docker, additional_services, haproxy_container, \ + links, Haproxy.cls_linked_services) + except Exception as e: + logger.info("Error loading ADDITIONAL_SERVICES: %s" % str(e)) + return None + logger.info("Linked service: %s", ", ".join(NewLinkHelper.get_service_links_str(links))) logger.info("Linked container: %s", ", ".join(NewLinkHelper.get_container_links_str(links))) return links diff --git a/haproxy/helper/new_link_helper.py b/haproxy/helper/new_link_helper.py index 0f1e974..fce21b1 100644 --- a/haproxy/helper/new_link_helper.py +++ b/haproxy/helper/new_link_helper.py @@ -15,6 +15,41 @@ def get_new_links(docker, haproxy_container): links = _calc_links(docker, linked_compose_services, project) return links, ["%s_%s" % (project, service) for service in linked_compose_services] +def get_additional_links(docker, additional_services, haproxy_container, links, linked_services): + networks_data = docker.networks() + haproxy_networks_ids = _find_container_networks_ids(haproxy_container, networks_data) + import pprint + for _container in docker.containers(): + container_id = _container.get("Id", "") + container = docker.inspect_container(container_id) + compose_project = container.get("Config", {}).get("Labels", {}).get("com.docker.compose.project", "") + compose_service = container.get("Config", {}).get("Labels", {}).get("com.docker.compose.service", "") + for _service in additional_services: + terms = _service.strip().split(":") + if len(terms) == 2: + if terms[0].strip() == compose_project and terms[1].strip() == compose_service: + container_networks_ids = _find_container_networks_ids(container, networks_data) + if set(container_networks_ids).intersection(haproxy_networks_ids): + if _service not in linked_services: + linked_services.append(_service) + container_name = container.get("Name").lstrip("/") + container_evvvars = _get_container_envvars(container) + endpoints = _get_container_endpoints(container, container_name) + links[container_id] = {"service_name": _service, + "container_envvars": container_evvvars, + "container_name": container_name, + "endpoints": endpoints, + "compose_service": compose_service, + "compose_project": compose_project} + else: + logger.info("Ignoring container '%s': no shared network with haproxy") + +def _find_container_networks_ids(container, networks_data): + ids = [] + for network in networks_data: + if container['Id'] in network['Containers'].keys(): + ids.append(network['Id']) + return ids def _calc_links(docker, linked_compose_services, project): links = {} @@ -76,7 +111,9 @@ def _get_linked_compose_services(networks, project): haproxy_links = [] for network in networks.itervalues(): - haproxy_links.extend(network.get("Links", [])) + network_links=network.get("Links", []) + if network_links: + haproxy_links.extend(network_links) linked_services = [] for link in haproxy_links: