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

Added "Services" env var for explicit declaration #233

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
1 change: 1 addition & 0 deletions haproxy/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def parse_additional_backend_settings(envvars):
HEALTH_CHECK = os.getenv("HEALTH_CHECK", "check inter 2000 rise 2 fall 3")
HTTP_BASIC_AUTH = os.getenv("HTTP_BASIC_AUTH")
HTTP_BASIC_AUTH_SECURE = os.getenv("HTTP_BASIC_AUTH_SECURE")
LINKED_SERVICES = os.getenv("SERVICES")
MAXCONN = os.getenv("MAXCONN", "4096")
MODE = os.getenv("MODE", "http")
MONITOR_PORT = os.getenv("MONITOR_PORT")
Expand Down
2 changes: 1 addition & 1 deletion haproxy/eventhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def polling_service_status_swarm_mode():
services = docker.services()
tasks = docker.tasks(filters={"desired-state": "running"})
_, linked_tasks = SwarmModeLinkHelper.get_task_links(tasks, services, Haproxy.cls_service_id,
Haproxy.cls_nets)
Haproxy.cls_nets, Haproxy.cls_namespace)
if cmp(Haproxy.cls_linked_tasks, linked_tasks) != 0:
add_haproxy_run_task("Tasks are updated")
except APIError as e:
Expand Down
5 changes: 3 additions & 2 deletions haproxy/haproxycfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class Haproxy(object):
cls_ca_certs = []
cls_nets = set()
cls_service_id = ""
cls_namespace = ""

def __init__(self, running_mode=RunningMode.LegacyMode):
logger.info("==========BEGIN==========")
Expand Down Expand Up @@ -117,10 +118,10 @@ def _init_swarm_mode_links():
logger.info("Docker API error, regressing to legacy links mode: %s" % e)
return None
haproxy_container_id = os.environ.get("HOSTNAME", "")
Haproxy.cls_service_id, Haproxy.cls_nets = SwarmModeLinkHelper.get_swarm_mode_haproxy_id_nets(docker,
Haproxy.cls_service_id, Haproxy.cls_nets, Haproxy.cls_namespace = SwarmModeLinkHelper.get_swarm_mode_haproxy_id_nets(docker,
haproxy_container_id)
links, Haproxy.cls_linked_tasks = SwarmModeLinkHelper.get_swarm_mode_links(docker, Haproxy.cls_service_id,
Haproxy.cls_nets)
Haproxy.cls_nets, Haproxy.cls_namespace)
logger.info("Linked service: %s", ", ".join(SwarmModeLinkHelper.get_service_links_str(links)))
logger.info("Linked container: %s", ", ".join(SwarmModeLinkHelper.get_container_links_str(links)))
return links
Expand Down
42 changes: 34 additions & 8 deletions haproxy/helper/compose_mode_link_helper.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
from haproxy.config import LINKED_SERVICES

logger = logging.getLogger("haproxy")

Expand Down Expand Up @@ -49,12 +50,25 @@ def _calc_links(docker, linked_compose_services, project):
compose_labels = container.get("Config", {}).get("Labels", {})
compose_project = compose_labels.get("com.docker.compose.project", "")
compose_service = compose_labels.get("com.docker.compose.service", "")


linked_service_names = {}
for x in str(LINKED_SERVICES).strip().split(";"):
if not x.strip():
break

service_values = x.strip().split(":")
service_name = "%s" % service_values[0]
if len(service_values) == 2:
linked_service_names[service_name] = {y: {} for y in service_values[1].strip().split(",") if y}
else:
linked_service_names[service_name] = {}

if compose_project == project and compose_service in linked_compose_services:
service_name = "%s_%s" % (compose_project, compose_service)
container_name = container.get("Name").lstrip("/")
container_evvvars = get_container_envvars(container)
endpoints = get_container_endpoints(container, container_name)
explicit_endpoints = linked_service_names.get(compose_service, {})
endpoints = get_container_endpoints(container, container_name, explicit_endpoints)
links[container_id] = {"service_name": service_name,
"container_envvars": container_evvvars,
"container_name": container_name,
Expand All @@ -64,10 +78,12 @@ def _calc_links(docker, linked_compose_services, project):
return links


def get_container_endpoints(container, container_name):
def get_container_endpoints(container, container_name, explicit_endpoints):
endpoints = {}
container_endpoints = container.get("Config", {}).get("ExposedPorts", {})
for k, v in container_endpoints.iteritems():
if not explicit_endpoints:
explicit_endpoints = container.get("Config", {}).get("ExposedPorts", {})

for k, v in explicit_endpoints.iteritems():
if k:
terms = k.split("/", 1)
port = terms[0]
Expand All @@ -80,7 +96,6 @@ def get_container_endpoints(container, container_name):
endpoints[k] = v
return endpoints


def get_container_envvars(container):
container_evvvars = []
envvars = container.get("Config", {}).get("Env", [])
Expand All @@ -105,14 +120,25 @@ def _get_linked_compose_services(networks, project):
if network_links:
haproxy_links.extend(network_links)

linked_service_names = []
if LINKED_SERVICES:
for x in str(LINKED_SERVICES).strip().split(";"):
if not x.strip():
break
service_values = x.strip().split(":")
if service_values:
linked_service_names.append("%s" % (service_values[0]))

linked_services = []
for link in haproxy_links:
terms = link.strip().split(":")
service = terms[0].strip()
service = terms[0].strip()
if service and service.startswith(prefix):
last = service.rfind("_")
linked_service = service[prefix_len:last]
if linked_service not in linked_services:
if linked_service_names and linked_service not in linked_service_names:
continue
if linked_service not in linked_services:
linked_services.append(linked_service)
return linked_services

Expand Down
40 changes: 31 additions & 9 deletions haproxy/helper/swarm_mode_link_helper.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging

import compose_mode_link_helper
from haproxy.config import SERVICE_PORTS_ENVVAR_NAME, LABEL_SWARM_MODE_DEACTIVATE
from haproxy.config import SERVICE_PORTS_ENVVAR_NAME, LABEL_SWARM_MODE_DEACTIVATE, LINKED_SERVICES

logger = logging.getLogger("haproxy")

Expand All @@ -13,6 +13,7 @@ def get_swarm_mode_haproxy_id_nets(docker, haproxy_container_short_id):
logger.info("Docker API error, regressing to legacy links mode: %s" % e)
return "", set()
labels = haproxy_container.get("Config", {}).get("Labels", {})
haproxy_namespace = labels.get("com.docker.stack.namespace", "")
haproxy_service_id = labels.get("com.docker.swarm.service.id", "")
if not haproxy_service_id:
logger.info("Dockercloud haproxy is not running in a service in SwarmMode")
Expand All @@ -22,18 +23,32 @@ def get_swarm_mode_haproxy_id_nets(docker, haproxy_container_short_id):
haproxy_container.get("NetworkSettings", {}).get("Networks", {}).iteritems()
if name != "ingress"])

return haproxy_service_id, haproxy_nets
return haproxy_service_id, haproxy_nets, haproxy_namespace


def get_swarm_mode_links(docker, haproxy_service_id, haproxy_nets):
def get_swarm_mode_links(docker, haproxy_service_id, haproxy_nets, haproxy_namespace):
services = docker.services()
tasks = docker.tasks(filters={"desired-state": "running"})
return get_task_links(tasks, services, haproxy_service_id, haproxy_nets)
return get_task_links(tasks, services, haproxy_service_id, haproxy_nets, haproxy_namespace)


def get_task_links(tasks, services, haproxy_service_id, haproxy_nets):
def get_task_links(tasks, services, haproxy_service_id, haproxy_nets, haproxy_namespace):
services_id_name = {s.get("ID"): s.get("Spec", {}).get("Name", "") for s in services}
services_id_labels = {s.get("ID"): s.get("Spec", {}).get("Labels", {}) for s in services}

linked_service_names = {}
if LINKED_SERVICES:
for x in str(LINKED_SERVICES).strip().split(";"):
if not x.strip():
break

service_values = x.strip().split(":")
service_name = "%s_%s" % (haproxy_namespace, service_values[0])
if len(service_values) == 2:
linked_service_names[service_name] = service_values[1]
else:
linked_service_names[service_name] = ""

links = {}
linked_tasks = {}
for task in tasks:
Expand All @@ -45,18 +60,25 @@ def get_task_links(tasks, services, haproxy_service_id, haproxy_nets):
task_slot = "%d" % task.get("Slot", 0)
task_service_id = task.get("ServiceID", "")
task_service_name = services_id_name.get(task_service_id, "")
task_labels = services_id_labels.get(task_service_id, {})

if LINKED_SERVICES and task_service_name not in linked_service_names:
continue

task_labels = services_id_labels.get(task_service_id, {})
if task_labels.get(LABEL_SWARM_MODE_DEACTIVATE, "").lower() == "true":
continue

container_name = ".".join([task_service_name, task_slot, task_id])
task_envvars = get_task_envvars(task.get("Spec", {}).get("ContainerSpec", {}).get("Env", []))

service_ports = ""
for task_envvar in task_envvars:
if task_envvar["key"] == SERVICE_PORTS_ENVVAR_NAME:
service_ports = task_envvar["value"]
if LINKED_SERVICES and linked_service_names.get(task_service_name, ""):
service_ports = linked_service_names[task_service_name]
else:
for task_envvar in task_envvars:
if task_envvar["key"] == SERVICE_PORTS_ENVVAR_NAME:
service_ports = task_envvar["value"]

task_ports = [x.strip() for x in service_ports.strip().split(",") if x.strip()]

task_ips = []
Expand Down