first step to refactor

This commit is contained in:
Joachim Lusiardi 2016-04-10 12:36:43 +02:00
parent 0a39d8c8b1
commit c3664b34d3
2 changed files with 74 additions and 48 deletions

View File

@ -9,21 +9,24 @@ import os
from socket import getaddrinfo
import logging
def get_if_available(dict, key, defValue):
if key in dict:
return dict[key]
else:
return defValue
def analyse_proxy_data(data):
"""Extracts the data for the proxy configuration (envrionment variable
'PROXY_DATA' and converts it to a dictionary."""
proxy_data = {}
for proxy_var in data['PROXY_DATA'].split(','):
t = proxy_var.split(":",1)
t = proxy_var.split(":", 1)
proxy_data[t[0]] = t[1]
return proxy_data
def analyse_env_vars(inspect_data):
"""Extracts the environment variables from the given result of an 'inspect
container' call."""
@ -35,6 +38,7 @@ def analyse_env_vars(inspect_data):
env_data[t[0]] = t[1]
return env_data
def handle_container(docker_client, id):
"""This function take a container's id and collects all data required
to create a proper proxy configuration. The configuration is then
@ -47,6 +51,7 @@ def handle_container(docker_client, id):
return names
return []
def get_resolving_domains_from_containers(docker_client):
container_ids = docker_client.containers(quiet=True)
@ -70,8 +75,8 @@ def get_resolving_domains_from_containers(docker_client):
return resolved_domains
if __name__ == '__main__':
if __name__ == '__main__':
client = Client(base_url='unix://var/run/docker.sock', version='1.15')
resolved_domains = get_resolving_domains_from_containers(client)

113
start.py
View File

@ -12,34 +12,37 @@ import threading
import list_domains
from docker import Client
cert_path='/data/haproxy'
cert_file='/data/haproxy/cert.pem'
pid_file='/haproxy.pid'
cert_path = '/data/haproxy'
cert_file = '/data/haproxy/cert.pem'
pid_file = '/haproxy.pid'
delay = 10
def hash_cert_file():
"""Creates the sha256 hash of the certifcate file for haproxy. If the file
"""Creates the sha256 hash of the certificate file for haproxy. If the file
does not exist, an empty string is returned.
"""
if not os.path.isfile(cert_file):
return ''
aFile = open(cert_file, 'rb')
hasher = hashlib.sha256()
buf = aFile.read(65536)
file_obj = open(cert_file, 'rb')
hash_generator = hashlib.sha256()
buf = file_obj.read(65536)
while len(buf) > 0:
hasher.update(buf)
buf = aFile.read(65536)
return hasher.digest()
hash_generator.update(buf)
buf = file_obj.read(65536)
return hash_generator.digest()
def setup_logging():
"""Sets up logging with a nice format"""
logging.basicConfig(format='%(asctime)s [%(levelname)s]: %(message)s', level=logging.INFO)
def get_pid():
"""This function reads the process id from the given file and returns as int."""
with open(pid_file, 'r') as file:
return int(file.read())
def kill_haproxy():
"""Stops the currently running instance of haproxy by issueing a kill signal to its pid."""
logging.info('killing haproxy')
@ -48,16 +51,19 @@ def kill_haproxy():
except OSError:
pass
def start_haproxy_ssl():
logging.info('starting haproxy SSL')
os.system('/usr/sbin/haproxy -f /haproxy_ssl.conf -p /haproxy.pid')
os.system('/usr/sbin/haproxy -f /haproxy_ssl.conf -p ' + pid_file)
return is_haproxy_running()
def start_haproxy():
logging.info('starting haproxy NON SSL')
os.system('/usr/sbin/haproxy -f /haproxy.conf -p /haproxy.pid')
os.system('/usr/sbin/haproxy -f /haproxy.conf -p ' + pid_file)
return False
def is_haproxy_running():
try:
os.kill(get_pid(), 0)
@ -65,6 +71,7 @@ def is_haproxy_running():
except OSError:
return False
def ssl_possible():
"""Check if a certificate is available."""
@ -73,67 +80,81 @@ def ssl_possible():
else:
return True
def create_haproxy_cert():
"""Combines the freshly created fullchain.pem and privkey.pem into /data/haproxy/cert.pem"""
logging.info('updating %s', cert_file)
os.system('DIR=`ls -td /data/config/live/*/ | head -1`; echo ${DIR}; mkdir -p /data/haproxy; cat ${DIR}/fullchain.pem ${DIR}/privkey.pem > /data/haproxy/cert.pem')
if not os.path.exists(cert_path):
logging.info('creating cert_path path: %s', cert_path)
os.mkdir(cert_path)
os.system(
'DIR=`ls -td /data/config/live/*/ | head -1`; echo ${DIR}; cat ${DIR}/fullchain.pem ${DIR}/privkey.pem > ' + cert_file)
def create_cert_data_standalone(domains):
domains = " -d ".join(domains)
os.system('/letsencrypt/letsencrypt-auto --config letencrypt.conf certonly --expand --force-renewal --duplicate --allow-subset-of-names --standalone-supported-challenges http-01 --http-01-port 54321 -d ' + domains)
os.system(
'/letsencrypt/letsencrypt-auto --config letencrypt.conf certonly --expand --force-renewal --duplicate --allow-subset-of-names --standalone-supported-challenges http-01 --http-01-port 54321 -d ' + domains)
def cert_watcher():
SSL_RUNNING=True
ssl_active = ssl_possible() and is_haproxy_running()
cert_file_hash = hash_cert_file()
while True:
logging.info('ping')
time.sleep(60)
if ssl_possible() and not SSL_RUNNING:
kill_haproxy()
start_haproxy_ssl()
if is_haproxy_running():
cert_file_hash = hash_cert_file()
logging.info('NON SSL -> SSL')
SSL_RUNNING=True
time.sleep(delay)
if not ssl_active:
if ssl_possible():
# we should be able to start with SSL, but ...
kill_haproxy()
start_haproxy_ssl()
if is_haproxy_running():
# running with SSL succeeded
cert_file_hash = hash_cert_file()
logging.info('NON SSL -> SSL')
ssl_active = True
else:
# something went wrong (maybe broken certificate) but without SSL we can run it
start_haproxy()
logging.info('NON SSL -> NON SSL')
else:
start_haproxy()
SSL_RUNNING=False
if SSL_RUNNING and cert_file_hash != hash_cert_file():
logging.info('cert has changed')
kill_haproxy()
start_haproxy_ssl()
if is_haproxy_running():
# currently not running with SSL but also no cert, so we do not attempt to start with SSL
pass
else:
if cert_file_hash != hash_cert_file():
# we are running with SSL and the certificate has changed so we need to restart haproxy
logging.info('cert has changed')
kill_haproxy()
start_haproxy_ssl()
if is_haproxy_running():
# restart with SSL succeeded, update hash
logging.info('SSL -> SSL')
else:
# restart with SSL failed, so we start without SSL again
start_haproxy()
logging.info('SSL -> NON SSL')
ssl_active = False
cert_file_hash = hash_cert_file()
logging.info('SSL -> SSL')
SSL_RUNNING=True
else:
start_haproxy()
logging.info('SSL -> NON SSL')
SSL_RUNNING=False
if __name__ == '__main__':
setup_logging()
logging.info('starting')
logging.info('starting ssl endpoint')
if not os.path.exists(cert_path):
logging.info('creating cert_path path: %s', cert_path)
os.mkdir(cert_path)
client = Client(base_url='unix://var/run/docker.sock', version='1.15')
cert_file_hash = hash_cert_file()
# try to start in SSL mode, no problem if that fails
logging.info('try in SSL mode')
SSL_RUNNING = start_haproxy_ssl()
if not SSL_RUNNING:
if not start_haproxy_ssl():
logging.info('SSL mode failed')
if not is_haproxy_running():
# tried to start haproxy and this failed, so we need to create a certificate and try again:
# - start non ssl haproxy to be able to get a valid cert
logging.info('try in NON SSL mode')
SSL_RUNNING = start_haproxy()
start_haproxy()
# - get all domains
resolved_domains = list_domains.get_resolving_domains_from_containers(client)
# - create cert