1
0
Fork 0

More adjustmemts

This commit is contained in:
Joao M 2022-08-24 02:33:21 +00:00
parent 7d959f892a
commit 877a4b3383
7 changed files with 69 additions and 36 deletions

View file

@ -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" ]

View file

@ -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

View file

@ -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:

View file

@ -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()

View file

@ -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

View file

@ -3,4 +3,4 @@ docker
jinja2 jinja2
pytest pytest
kubernetes kubernetes
numpy deepdiff

View file

@ -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