|
1 | 1 | import logging |
| 2 | + |
2 | 3 | import compose_mode_link_helper |
| 4 | +from haproxy.config import SERVICE_PORTS_ENVVAR_NAME |
3 | 5 |
|
4 | 6 | logger = logging.getLogger("haproxy") |
5 | 7 |
|
6 | 8 |
|
7 | | -def get_swarm_mode_links(docker, haproxy_container_short_id): |
| 9 | +def get_swarm_mode_haproxy_id_nets(docker, haproxy_container_short_id): |
8 | 10 | try: |
9 | 11 | haproxy_container = docker.inspect_container(haproxy_container_short_id) |
10 | 12 | except Exception as e: |
11 | 13 | logger.info("Docker API error, regressing to legacy links mode: %s" % e) |
12 | | - return {}, set() |
| 14 | + return "", set() |
13 | 15 | labels = haproxy_container.get("Config", {}).get("Labels", {}) |
14 | | - service_id = labels.get("com.docker.swarm.node.id", "") |
15 | | - service_name = labels.get("com.docker.swarm.service.name", "") |
16 | | - task_id = labels.get("com.docker.swarm.task.id", "") |
17 | | - task_name = labels.get("com.docker.swarm.task.name", "") |
18 | | - if not (service_id and service_name and task_id and task_name): |
| 16 | + haproxy_service_id = labels.get("com.docker.swarm.service.id", "") |
| 17 | + if not haproxy_service_id: |
19 | 18 | logger.info("Dockercloud haproxy is not running in a service in SwarmMode") |
20 | | - return {}, set() |
| 19 | + return "", set() |
21 | 20 |
|
22 | | - nets = haproxy_container.get("NetworkSettings", {}).get("Networks", {}) |
23 | | - net_ids = [network.get("NetworkID", "") for network in nets.values()] |
| 21 | + haproxy_nets = set([network.get("NetworkID", "") for network in |
| 22 | + haproxy_container.get("NetworkSettings", {}).get("Networks", {}).values()]) |
24 | 23 |
|
25 | | - linked_containers_ids = [] |
26 | | - for net_id in net_ids: |
27 | | - network_inspect = docker.inspect_network(net_id) |
28 | | - linked_containers_ids.extend(network_inspect.get("Containers", {}).keys()) |
| 24 | + return haproxy_service_id, haproxy_nets |
29 | 25 |
|
30 | | - linked_containers = {} |
31 | | - for linked_containers_id in linked_containers_ids: |
32 | | - try: |
33 | | - linked_container = docker.inspect_container(linked_containers_id) |
34 | | - except Exception as e: |
35 | | - logger.info("Docker API error: %s" % e) |
36 | | - continue |
37 | | - if linked_container.get("Config", {}).get("Labels", {}).get("com.docker.swarm.service.name", |
38 | | - "") != service_name: |
39 | | - linked_containers[linked_containers_id] = linked_container |
40 | 26 |
|
41 | | - links, services = _calc_links(linked_containers) |
42 | | - return links, services, net_ids |
| 27 | +def get_swarm_mode_links(docker, haproxy_service_id, haproxy_nets): |
| 28 | + services = docker.services() |
| 29 | + tasks = docker.tasks(filters={"desired-state": "running"}) |
| 30 | + links, linked_tasks = get_task_links(tasks, services, haproxy_service_id, haproxy_nets) |
| 31 | + return links, linked_tasks |
43 | 32 |
|
44 | 33 |
|
45 | | -def _calc_links(containers): |
| 34 | +def get_task_links(tasks, services, haproxy_service_id, haproxy_nets): |
| 35 | + services_id_name = {s.get("ID"): s.get("Spec", {}).get("Name", "") for s in services} |
46 | 36 | links = {} |
47 | | - services = set() |
48 | | - for container_id, container in containers.items(): |
49 | | - container_name = container.get("Name").lstrip("/") |
50 | | - service_name = container.get("Config", {}).get("Labels", {}).get("com.docker.swarm.service.name", "") |
51 | | - container_evvvars = get_container_envvars(container) |
52 | | - endpoints = get_container_endpoints(container, container_name) |
53 | | - links[container_id] = {"service_name": service_name, |
54 | | - "container_envvars": container_evvvars, |
55 | | - "container_name": container_name, |
56 | | - "endpoints": endpoints, |
57 | | - } |
58 | | - services.add(service_name) |
59 | | - return links, services |
60 | | - |
61 | | - |
62 | | -def get_container_endpoints(container, container_name): |
63 | | - return compose_mode_link_helper.get_container_endpoints(container, container_name) |
64 | | - |
65 | | - |
66 | | -def get_container_envvars(container): |
67 | | - return compose_mode_link_helper.get_container_envvars(container) |
| 37 | + linked_tasks = set() |
| 38 | + for task in tasks: |
| 39 | + task_nets = [network.get("Network", {}).get("ID", "") for network in task.get("NetworksAttachments", [])] |
| 40 | + task_service_id = task.get("ServiceID", "") |
| 41 | + task_nets_attached = haproxy_nets.intersection(set(task_nets)) |
| 42 | + if task_service_id != haproxy_service_id and task_nets_attached: |
| 43 | + task_id = task.get("ID", "") |
| 44 | + task_slot = "%d" % task.get("Slot", 0) |
| 45 | + task_service_id = task.get("ServiceID", "") |
| 46 | + task_service_name = services_id_name.get(task_service_id, "") |
| 47 | + container_name = ".".join([task_service_name, task_slot, task_id]) |
| 48 | + task_envvars = get_task_envvars(task.get("Spec", {}).get("ContainerSpec", {}).get("Env", [])) |
| 49 | + |
| 50 | + service_ports = "" |
| 51 | + for task_envvar in task_envvars: |
| 52 | + if task_envvar["key"] == SERVICE_PORTS_ENVVAR_NAME: |
| 53 | + service_ports = task_envvar["value"] |
| 54 | + task_ports = [x.strip() for x in service_ports.strip().split(",") if x.strip()] |
| 55 | + |
| 56 | + task_ips = [] |
| 57 | + for network_attachment in task.get("NetworksAttachments", []): |
| 58 | + if network_attachment.get("Network", {}).get("ID", "") in task_nets_attached: |
| 59 | + task_ips = network_attachment.get("Addresses", []) |
| 60 | + break |
| 61 | + |
| 62 | + if task_ips: |
| 63 | + task_ip = task_ips[0].split("/")[0] |
| 64 | + else: |
| 65 | + task_ip = container_name |
| 66 | + |
| 67 | + task_endpoints = {"%s/tcp" % port: "tcp://%s:%s" % (task_ip, port) for port in task_ports} |
| 68 | + |
| 69 | + links[task_id] = {"endpoints": task_endpoints, "container_name": container_name, |
| 70 | + "service_name": task_service_name, "container_envvars": task_envvars} |
| 71 | + linked_tasks.add(task_id) |
| 72 | + return links, linked_tasks |
| 73 | + |
| 74 | + |
| 75 | +def get_task_envvars(envvars): |
| 76 | + new_envvars = [] |
| 77 | + for _envvar in envvars: |
| 78 | + terms = _envvar.split("=", 1) |
| 79 | + envvar = {"key": terms[0]} |
| 80 | + if len(terms) == 2: |
| 81 | + envvar["value"] = terms[1] |
| 82 | + else: |
| 83 | + envvar["value"] = "" |
| 84 | + new_envvars.append(envvar) |
| 85 | + return new_envvars |
68 | 86 |
|
69 | 87 |
|
70 | 88 | def get_service_links_str(links): |
|
0 commit comments