More adjustmemts
This commit is contained in:
parent
7d959f892a
commit
877a4b3383
7 changed files with 69 additions and 36 deletions
14
Dockerfile
14
Dockerfile
|
|
@ -11,11 +11,11 @@ COPY assets /
|
||||||
|
|
||||||
RUN apk add --no-cache haproxy bash python3 py3-pip py-yaml docker certbot openssl \
|
RUN apk add --no-cache haproxy bash python3 py3-pip py-yaml docker certbot openssl \
|
||||||
&& ln -s /usr/bin/python3 /usr/bin/python \
|
&& ln -s /usr/bin/python3 /usr/bin/python \
|
||||||
&& pip3 install --upgrade pip
|
&& pip3 install --upgrade pip \
|
||||||
# \
|
&& pip install -r requirements.txt \
|
||||||
# && pip install -r requirements.txt \
|
&& openssl dhparam -out /etc/haproxy/dhparam 2048 \
|
||||||
# && pytest -s tests/ \
|
&& openssl dhparam -out /etc/haproxy/dhparam-1024 1024
|
||||||
# && openssl dhparam -out /etc/haproxy/dhparam 2048 \
|
|
||||||
# && openssl dhparam -out /etc/haproxy/dhparam-1024 1024
|
|
||||||
|
|
||||||
# CMD ["/bin/bash", "-c", "/scripts/haproxy.sh" ]
|
# && pytest -s tests/ \
|
||||||
|
|
||||||
|
CMD ["/usr/bin/python", "-u", "/scripts/main.py" ]
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,8 @@ class HaproxyConfigGenerator:
|
||||||
self.mapping.setdefault("letsencrypt", {"email": ""})
|
self.mapping.setdefault("letsencrypt", {"email": ""})
|
||||||
self.mapping["ssl_mode"] = self.mapping["ssl_mode"].lower()
|
self.mapping["ssl_mode"] = self.mapping["ssl_mode"].lower()
|
||||||
self.label = DockerLabelHandler(mapping['lookup_label'] if 'lookup_label' in mapping else "easyhaproxy")
|
self.label = DockerLabelHandler(mapping['lookup_label'] if 'lookup_label' in mapping else "easyhaproxy")
|
||||||
self.ssl_cert_haproxy = ssl_cert_folder + "/haproxy"
|
|
||||||
self.ssl_cert_letsecncrypt = ssl_cert_folder + "/letsencrypt"
|
|
||||||
self.letsencrypt_hosts = []
|
self.letsencrypt_hosts = []
|
||||||
|
self.serving_hosts = []
|
||||||
self.certs = {}
|
self.certs = {}
|
||||||
|
|
||||||
def generate(self, container_metadata = None):
|
def generate(self, container_metadata = None):
|
||||||
|
|
@ -134,6 +133,7 @@ class HaproxyConfigGenerator:
|
||||||
|
|
||||||
for hostname in d[host_label].split(","):
|
for hostname in d[host_label].split(","):
|
||||||
hostname = hostname.strip()
|
hostname = hostname.strip()
|
||||||
|
self.serving_hosts.append("%s:%s" % (hostname, port))
|
||||||
easymapping[port]["hosts"].setdefault(hostname, {})
|
easymapping[port]["hosts"].setdefault(hostname, {})
|
||||||
easymapping[port]["hosts"][hostname].setdefault("containers", [])
|
easymapping[port]["hosts"][hostname].setdefault("containers", [])
|
||||||
easymapping[port]["hosts"][hostname].setdefault("letsencrypt", False)
|
easymapping[port]["hosts"][hostname].setdefault("letsencrypt", False)
|
||||||
|
|
@ -166,11 +166,9 @@ class HaproxyConfigGenerator:
|
||||||
# handle SSL
|
# handle SSL
|
||||||
ssl_label = self.label.create([definition, "sslcert"])
|
ssl_label = self.label.create([definition, "sslcert"])
|
||||||
if self.label.has_label(ssl_label):
|
if self.label.has_label(ssl_label):
|
||||||
filename = "{}/{}.pem".format(
|
filename = "{}.pem".format(d[host_label])
|
||||||
self.ssl_cert_haproxy, d[host_label]
|
|
||||||
)
|
|
||||||
easymapping[port]["ssl"] = True
|
easymapping[port]["ssl"] = True
|
||||||
self.certs[filename] = base64.b64decode(d[ssl_label])
|
self.certs[filename] = base64.b64decode(d[ssl_label]).decode('ascii')
|
||||||
|
|
||||||
if self.label.get_bool(self.label.create([definition, "ssl"])):
|
if self.label.get_bool(self.label.create([definition, "ssl"])):
|
||||||
easymapping[port]["ssl"] = True
|
easymapping[port]["ssl"] = True
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import subprocess
|
import subprocess
|
||||||
import shlex
|
import shlex
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
class Functions:
|
class Functions:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
@ -19,7 +18,7 @@ class Functions:
|
||||||
if message is None or message == "":
|
if message is None or message == "":
|
||||||
return
|
return
|
||||||
|
|
||||||
if not isinstance(message, (list, tuple, np.ndarray)):
|
if not isinstance(message, (list, tuple)):
|
||||||
message = [message]
|
message = [message]
|
||||||
|
|
||||||
for line in message:
|
for line in message:
|
||||||
|
|
@ -27,7 +26,7 @@ class Functions:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run_bash(source, command, log_output=True, return_result=True):
|
def run_bash(source, command, log_output=True, return_result=True):
|
||||||
if not isinstance(command, (list, tuple, np.ndarray)):
|
if not isinstance(command, (list, tuple)):
|
||||||
command = shlex.split(command)
|
command = shlex.split(command)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
32
src/main.py
32
src/main.py
|
|
@ -3,6 +3,7 @@ from processor import ProcessorInterface
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
from deepdiff import DeepDiff
|
||||||
|
|
||||||
easyhaproxy_config = "/etc/haproxy/easyconfig.yml"
|
easyhaproxy_config = "/etc/haproxy/easyconfig.yml"
|
||||||
haproxy_config = "/etc/haproxy/haproxy.cfg"
|
haproxy_config = "/etc/haproxy/haproxy.cfg"
|
||||||
|
|
@ -17,9 +18,9 @@ def start():
|
||||||
os.makedirs(certs_letsencrypt, exist_ok=True)
|
os.makedirs(certs_letsencrypt, exist_ok=True)
|
||||||
os.makedirs(certs_haproxy, exist_ok=True)
|
os.makedirs(certs_haproxy, exist_ok=True)
|
||||||
|
|
||||||
Functions.save(haproxy_config, processor_obj.get_haproxy_conf())
|
processor_obj.save_config(haproxy_config)
|
||||||
for cert in processor_obj.get_certs():
|
processor_obj.save_certs(certs_haproxy)
|
||||||
Functions.save(certs_haproxy, processor_obj.get_certs(cert))
|
Functions.log('EASYHAPROXY', 'info', 'Found hosts: %s' % ", ".join(processor_obj.get_hosts())) # Needs to after save_config
|
||||||
|
|
||||||
#configs = Functions.run_bash('HAPROXY', 'ls /etc/haproxy/conf.d/*.cfg', log_output=False)
|
#configs = Functions.run_bash('HAPROXY', 'ls /etc/haproxy/conf.d/*.cfg', log_output=False)
|
||||||
x = Thread(target=Functions.run_bash, args=("HAPROXY", "/usr/sbin/haproxy -W -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /var/run/haproxy.sock", True, False))
|
x = Thread(target=Functions.run_bash, args=("HAPROXY", "/usr/sbin/haproxy -W -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /var/run/haproxy.sock", True, False))
|
||||||
|
|
@ -27,6 +28,22 @@ def start():
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
|
try:
|
||||||
|
old_parsed = processor_obj.get_parsed_object()
|
||||||
|
processor_obj.refresh()
|
||||||
|
if DeepDiff(old_parsed, processor_obj.get_parsed_object()) != {} or not x.is_alive():
|
||||||
|
Functions.log('EASYHAPROXY', 'info', 'New configuration found. Reloading...')
|
||||||
|
processor_obj.save_config(haproxy_config)
|
||||||
|
processor_obj.save_certs(certs_haproxy)
|
||||||
|
Functions.log('EASYHAPROXY', 'info', 'Found hosts: %s' % ", ".join(processor_obj.get_hosts())) # Needs to after save_config
|
||||||
|
pid = "".join(Functions().run_bash("HAPROXY", "cat /run/haproxy.pid", log_output=False))
|
||||||
|
x = Thread(target=Functions.run_bash, args=("HAPROXY", "/usr/sbin/haproxy -W -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -x /var/run/haproxy.sock -sf %s" % (pid), True, False))
|
||||||
|
x.start()
|
||||||
|
except Exception as e:
|
||||||
|
Functions.log('EASYHAPROXY', 'error', "Err: %s" % (e))
|
||||||
|
Functions.log('EASYHAPROXY', 'info', 'Heartbeat')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
@ -38,12 +55,13 @@ def main():
|
||||||
Functions.log('INIT', 'info', "\___\__,_/__/\_, | |_||_\__,_| .__/_| \___/_\_\\_, |")
|
Functions.log('INIT', 'info', "\___\__,_/__/\_, | |_||_\__,_| .__/_| \___/_\_\\_, |")
|
||||||
Functions.log('INIT', 'info', " |__/ |_| |__/ ")
|
Functions.log('INIT', 'info', " |__/ |_| |__/ ")
|
||||||
|
|
||||||
Functions.log('INIT', 'INFO', os.getenv("RELEASE_VERSION"))
|
Functions.log('INIT', 'info', "Release: %s" % (os.getenv("RELEASE_VERSION")))
|
||||||
Functions.log('INIT', 'INFO', "")
|
Functions.log('INIT', 'info', 'Environment:')
|
||||||
Functions.log('INIT', 'INFO', 'Environment:')
|
|
||||||
for name, value in os.environ.items():
|
for name, value in os.environ.items():
|
||||||
if "HAPROXY" in name:
|
if "HAPROXY" in name:
|
||||||
print("- {0}: {1}".format(name, value))
|
Functions.log('INIT', 'info', "- {0}: {1}".format(name, value))
|
||||||
|
|
||||||
|
start()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
@ -34,11 +34,7 @@ class ContainerEnv:
|
||||||
class ProcessorInterface:
|
class ProcessorInterface:
|
||||||
def __init__(self, filename = None):
|
def __init__(self, filename = None):
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.letsencrypt_hosts = None
|
self.refresh()
|
||||||
self.parsed_object = None
|
|
||||||
self.cfg = None
|
|
||||||
self.inspect_network()
|
|
||||||
self.parse()
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def factory(mode):
|
def factory(mode):
|
||||||
|
|
@ -51,9 +47,17 @@ class ProcessorInterface:
|
||||||
elif mode == "kubernetes":
|
elif mode == "kubernetes":
|
||||||
return Swarm()
|
return Swarm()
|
||||||
else:
|
else:
|
||||||
Functions.log("FACTORY", "error", "Expected mode to be 'static', 'docker', 'swarm' or 'kubernetes'. I got " + mode)
|
Functions.log("FACTORY", "error", "Expected mode to be 'static', 'docker', 'swarm' or 'kubernetes'. I got '%s'" % (mode))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
self.letsencrypt_hosts = None
|
||||||
|
self.parsed_object = None
|
||||||
|
self.cfg = None
|
||||||
|
self.hosts = None
|
||||||
|
self.inspect_network()
|
||||||
|
self.parse()
|
||||||
|
|
||||||
def inspect_network(self):
|
def inspect_network(self):
|
||||||
#Abstract
|
#Abstract
|
||||||
pass
|
pass
|
||||||
|
|
@ -65,6 +69,9 @@ class ProcessorInterface:
|
||||||
def get_letsencrypt_hosts(self):
|
def get_letsencrypt_hosts(self):
|
||||||
return self.letsencrypt_hosts
|
return self.letsencrypt_hosts
|
||||||
|
|
||||||
|
def get_hosts(self):
|
||||||
|
return self.hosts
|
||||||
|
|
||||||
def get_parsed_object(self):
|
def get_parsed_object(self):
|
||||||
return self.parsed_object
|
return self.parsed_object
|
||||||
|
|
||||||
|
|
@ -77,8 +84,16 @@ class ProcessorInterface:
|
||||||
def get_haproxy_conf(self):
|
def get_haproxy_conf(self):
|
||||||
conf = self.cfg.generate(self.parsed_object)
|
conf = self.cfg.generate(self.parsed_object)
|
||||||
self.letsencrypt_hosts = self.cfg.letsencrypt_hosts
|
self.letsencrypt_hosts = self.cfg.letsencrypt_hosts
|
||||||
|
self.hosts = self.cfg.serving_hosts
|
||||||
return conf
|
return conf
|
||||||
|
|
||||||
|
def save_config(self, filename):
|
||||||
|
Functions.save(filename, self.get_haproxy_conf())
|
||||||
|
|
||||||
|
def save_certs(self, path):
|
||||||
|
for cert in self.get_certs():
|
||||||
|
Functions.save("{0}/{1}".format(path, cert), self.get_certs(cert))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Static(ProcessorInterface):
|
class Static(ProcessorInterface):
|
||||||
|
|
@ -125,13 +140,15 @@ class Swarm(ProcessorInterface):
|
||||||
|
|
||||||
|
|
||||||
class Kubernetes(ProcessorInterface):
|
class Kubernetes(ProcessorInterface):
|
||||||
def inspect_network(self):
|
def __init__(self, filename = None):
|
||||||
config.load_incluster_config()
|
config.load_incluster_config()
|
||||||
|
self.api_instance = client.CoreV1Api()
|
||||||
|
self.v1 = client.NetworkingV1Api()
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
api_instance = client.CoreV1Api()
|
def inspect_network(self):
|
||||||
v1 = client.NetworkingV1Api()
|
|
||||||
|
|
||||||
ret = v1.list_ingress_for_all_namespaces(watch=False)
|
ret = self.v1.list_ingress_for_all_namespaces(watch=False)
|
||||||
|
|
||||||
self.parsed_object = {}
|
self.parsed_object = {}
|
||||||
for i in ret.items:
|
for i in ret.items:
|
||||||
|
|
@ -152,7 +169,7 @@ class Kubernetes(ProcessorInterface):
|
||||||
rule_data["easyhaproxy.%s_%s.localport" % (definition, port_number)] = port_number
|
rule_data["easyhaproxy.%s_%s.localport" % (definition, port_number)] = port_number
|
||||||
service_name = rule.http.paths[0].backend.service.name
|
service_name = rule.http.paths[0].backend.service.name
|
||||||
try:
|
try:
|
||||||
api_response = api_instance.read_namespaced_service(service_name, i.metadata.namespace)
|
api_response = self.api_instance.read_namespaced_service(service_name, i.metadata.namespace)
|
||||||
cluster_ip = api_response.spec.cluster_ip
|
cluster_ip = api_response.spec.cluster_ip
|
||||||
except ApiException as e:
|
except ApiException as e:
|
||||||
cluster_ip = None
|
cluster_ip = None
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,4 @@ docker
|
||||||
jinja2
|
jinja2
|
||||||
pytest
|
pytest
|
||||||
kubernetes
|
kubernetes
|
||||||
numpy
|
deepdiff
|
||||||
|
|
@ -78,3 +78,4 @@ backend srv_{{ host }}
|
||||||
backend letsencrypt_backend
|
backend letsencrypt_backend
|
||||||
mode http
|
mode http
|
||||||
server certbot 127.0.0.1:2080
|
server certbot 127.0.0.1:2080
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue