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

Commit a26fb7f

Browse files
committed
Merge branch 'staging'
2 parents b0e63b3 + f289780 commit a26fb7f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+4025
-1178
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ output
88

99
# Packages
1010
*.egg
11+
*.eggs
1112
*.egg-info
1213
dist
1314
build
@@ -38,3 +39,4 @@ nosetests.xml
3839
.project
3940
.pydevproject
4041
.idea
42+
.DS_Store

Dockerfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,5 @@ ENV RSYSLOG_DESTINATION=127.0.0.1 \
2727
SSL_BIND_CIPHERS="ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA" \
2828
HEALTH_CHECK="check"
2929

30-
3130
EXPOSE 80 443 1936
3231
CMD ["dockercloud-haproxy"]

README.md

Lines changed: 169 additions & 96 deletions
Large diffs are not rendered by default.

haproxy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.0.1"
1+
__version__ = "1.2"

haproxy/config.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import os
2+
import re
3+
4+
5+
def parse_extra_bind_settings(extra_bind_settings):
6+
bind_dict = {}
7+
if extra_bind_settings:
8+
settings = re.split(r'(?<!\\),', extra_bind_settings)
9+
for setting in settings:
10+
term = setting.split(":", 1)
11+
if len(term) == 2:
12+
bind_dict[term[0].strip().replace("\,", ",")] = term[1].strip().replace("\,", ",")
13+
return bind_dict
14+
15+
16+
# envvar
17+
DEFAULT_SSL_CERT = os.getenv("DEFAULT_SSL_CERT") or os.getenv("SSL_CERT")
18+
EXTRA_SSL_CERT = os.getenv("EXTRA_SSL_CERTS")
19+
DEFAULT_CA_CERT = os.getenv("CA_CERT")
20+
MAXCONN = os.getenv("MAXCONN", "4096")
21+
MODE = os.getenv("MODE", "http")
22+
OPTION = os.getenv("OPTION", "redispatch, httplog, dontlognull, forwardfor")
23+
RSYSLOG_DESTINATION = os.getenv("RSYSLOG_DESTINATION", "127.0.0.1")
24+
SSL_BIND_CIPHERS = os.getenv("SSL_BIND_CIPHERS")
25+
SSL_BIND_OPTIONS = os.getenv("SSL_BIND_OPTIONS")
26+
STATS_AUTH = os.getenv("STATS_AUTH", "stats:stats")
27+
STATS_PORT = os.getenv("STATS_PORT", "1936")
28+
TIMEOUT = os.getenv("TIMEOUT", "connect 5000, client 50000, server 50000")
29+
HEALTH_CHECK = os.getenv("HEALTH_CHECK", "check inter 2000 rise 2 fall 3")
30+
EXTRA_GLOBAL_SETTINGS = os.getenv("EXTRA_GLOBAL_SETTINGS")
31+
EXTRA_DEFAULT_SETTINGS = os.getenv("EXTRA_DEFAULT_SETTINGS")
32+
EXTRA_BIND_SETTINGS = parse_extra_bind_settings(os.getenv("EXTRA_BIND_SETTINGS"))
33+
HTTP_BASIC_AUTH = os.getenv("HTTP_BASIC_AUTH")
34+
MONITOR_URI = os.getenv("MONITOR_URI")
35+
MONITOR_PORT = os.getenv("MONITOR_PORT")
36+
BALANCE = os.getenv("BALANCE", "roundrobin")
37+
HAPROXY_CONTAINER_URI = os.getenv("DOCKERCLOUD_CONTAINER_API_URI")
38+
HAPROXY_SERVICE_URI = os.getenv("DOCKERCLOUD_SERVICE_API_URI")
39+
API_AUTH = os.getenv("DOCKERCLOUD_AUTH")
40+
DEBUG = os.getenv("DEBUG", False)
41+
LINK_MODE = ""
42+
43+
# const
44+
CERT_DIR = "/certs/"
45+
CACERT_DIR = "/cacerts/"
46+
HAPROXY_CONFIG_FILE = "/haproxy.cfg"
47+
HAPROXY_RUN_COMMAND = ['/usr/sbin/haproxy', '-f', HAPROXY_CONFIG_FILE, '-db', '-q']
48+
API_RETRY = 10 # seconds
49+
PID_FILE = "/tmp/dockercloud-haproxy.pid"
50+
51+
# regular expressions
52+
SERVICE_NAME_MATCH = re.compile(r"(.+)_\d+$")
53+
BACKEND_MATCH = re.compile(r"(?P<proto>tcp|udp):\/\/(?P<addr>[^:]*):(?P<port>.*)")
54+
SERVICE_ALIAS_MATCH = re.compile(r"_PORT_\d{1,5}_(TCP|UDP)$")
55+
DETAILED_SERVICE_ALIAS_MATCH = re.compile(r"_\d+_PORT_\d{1,5}_(TCP|UDP)$")
56+
ENV_SERVICE_ALIAS_MATCH = re.compile(r"_ENV_")
57+
ENV_DETAILED_SERVICE_ALIAS_MATCH = re.compile(r"_\d+_ENV")

haproxy/eventhandler.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import json
2+
import logging
3+
4+
import dockercloud
5+
from compose.cli.docker_client import docker_client
6+
from docker.errors import APIError
7+
8+
import config
9+
import helper.cloud_link_helper
10+
from haproxycfg import run_haproxy, Haproxy
11+
from utils import get_uuid_from_resource_uri
12+
13+
logger = logging.getLogger("haproxy")
14+
15+
16+
def on_cloud_event(message):
17+
logger.debug(message)
18+
logger.debug(Haproxy.cls_linked_services)
19+
try:
20+
event = json.loads(message)
21+
except ValueError:
22+
logger.info("event is not a valid json message")
23+
return
24+
25+
# When service scale up/down or container start/stop/terminate/redeploy, reload the service
26+
if event.get("state", "") not in ["In progress", "Pending", "Terminating", "Starting", "Scaling", "Stopping"] and \
27+
event.get("type", "").lower() in ["container", "service"] and \
28+
len(set(Haproxy.cls_linked_services).intersection(set(event.get("parents", [])))) > 0:
29+
msg = "Docker Cloud Event: %s %s is %s" % (
30+
event["type"], get_uuid_from_resource_uri(event.get("resource_uri", "")), event["state"].lower())
31+
run_haproxy(msg)
32+
33+
# Add/remove services linked to haproxy
34+
if event.get("state", "") == "Success" and config.HAPROXY_SERVICE_URI in event.get("parents", []):
35+
run_haproxy("Docker Cloud Event: New action is executed on the Haproxy container")
36+
37+
38+
def on_websocket_open():
39+
helper.cloud_link_helper.LINKED_CONTAINER_CACHE.clear()
40+
run_haproxy("Websocket open")
41+
42+
43+
def on_websocket_close():
44+
logger.info("Websocket close")
45+
46+
47+
def on_user_reload(signum, frame):
48+
run_haproxy("User reload")
49+
50+
51+
def listen_dockercloud_events():
52+
events = dockercloud.Events()
53+
events.on_open(on_websocket_open)
54+
events.on_close(on_websocket_close)
55+
events.on_message(on_cloud_event)
56+
events.run_forever()
57+
58+
59+
def listen_docker_events():
60+
try:
61+
docker = docker_client()
62+
docker.ping()
63+
for event in docker.events(decode=True):
64+
logger.debug(event)
65+
attr = event.get("Actor", {}).get("Attributes")
66+
compose_project = attr.get("com.docker.compose.project", "")
67+
compose_service = attr.get("com.docker.compose.service", "")
68+
container_name = attr.get("name", "")
69+
event_action = event.get("Action", "")
70+
service = "%s_%s" % (compose_project, compose_service)
71+
if service in Haproxy.cls_linked_services and event_action in ["start", "die"]:
72+
msg = "Docker event: container %s %s" % (container_name, event_action)
73+
run_haproxy(msg)
74+
except APIError as e:
75+
logger.info("Docker API error: %s" % e)

0 commit comments

Comments
 (0)