1
0
Fork 0

Fix lint errors

This commit is contained in:
Joao Gilberto Magalhaes 2026-01-22 22:05:49 -05:00
parent 62e5c054f4
commit dc28b18351
10 changed files with 124 additions and 125 deletions

View file

@ -5,7 +5,7 @@ import re
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
from functions import loggerEasyHaproxy from functions import logger_easyhaproxy
class DockerLabelHandler: class DockerLabelHandler:
@ -40,7 +40,7 @@ class DockerLabelHandler:
try: try:
return json.loads(value) return json.loads(value)
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
loggerEasyHaproxy.error( logger_easyhaproxy.error(
f"Invalid JSON in label '{label}': {value}. Error: {e}. Using default value." f"Invalid JSON in label '{label}': {value}. Error: {e}. Using default value."
) )
return default_value return default_value
@ -78,7 +78,7 @@ class HaproxyConfigGenerator:
self.global_plugin_configs = [] self.global_plugin_configs = []
except Exception as e: except Exception as e:
# If plugin system fails to initialize, log but continue # If plugin system fails to initialize, log but continue
loggerEasyHaproxy.warning(f"Failed to initialize plugin system: {e}") logger_easyhaproxy.warning(f"Failed to initialize plugin system: {e}")
self.plugin_manager = None self.plugin_manager = None
self.global_plugin_configs = [] self.global_plugin_configs = []
@ -112,7 +112,7 @@ class HaproxyConfigGenerator:
global_configs = [r.haproxy_config for r in global_results if r.haproxy_config] global_configs = [r.haproxy_config for r in global_results if r.haproxy_config]
self.global_plugin_configs.extend(global_configs) self.global_plugin_configs.extend(global_configs)
except Exception as e: except Exception as e:
loggerEasyHaproxy.warning(f"Failed to execute global plugins: {e}") logger_easyhaproxy.warning(f"Failed to execute global plugins: {e}")
templates_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'templates') templates_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'templates')
file_loader = FileSystemLoader(templates_dir) file_loader = FileSystemLoader(templates_dir)
@ -200,7 +200,7 @@ class HaproxyConfigGenerator:
for hostname in sorted(d[host_label].split(",")): for hostname in sorted(d[host_label].split(",")):
hostname = hostname.strip() hostname = hostname.strip()
self.serving_hosts.append("%s:%s" % (hostname, port)) self.serving_hosts.append(f"{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("certbot", False) easymapping[port]["hosts"][hostname].setdefault("certbot", False)
@ -283,7 +283,7 @@ class HaproxyConfigGenerator:
if result.metadata["fcgi_app_definition"] not in self.global_plugin_configs: if result.metadata["fcgi_app_definition"] not in self.global_plugin_configs:
self.global_plugin_configs.append(result.metadata["fcgi_app_definition"]) self.global_plugin_configs.append(result.metadata["fcgi_app_definition"])
except Exception as e: except Exception as e:
loggerEasyHaproxy.warning(f"Failed to execute domain plugins for {hostname}: {e}") logger_easyhaproxy.warning(f"Failed to execute domain plugins for {hostname}: {e}")
easymapping[port]["hosts"][hostname]["plugin_configs"] = [] easymapping[port]["hosts"][hostname]["plugin_configs"] = []
else: else:
easymapping[port]["hosts"][hostname]["plugin_configs"] = [] easymapping[port]["hosts"][hostname]["plugin_configs"] = []

View file

@ -86,7 +86,7 @@ class ContainerEnv:
env_vars["certbot"]["eab_hmac_key"] = os.environ['EASYHAPROXY_CERTBOT_EAB_HMAC_KEY'] = resp["eab_hmac_key"] env_vars["certbot"]["eab_hmac_key"] = os.environ['EASYHAPROXY_CERTBOT_EAB_HMAC_KEY'] = resp["eab_hmac_key"]
else: else:
del os.environ["EASYHAPROXY_CERTBOT_EMAIL"] del os.environ["EASYHAPROXY_CERTBOT_EMAIL"]
loggerCertbot.error("Could not obtain ZeroSSL credentials " + resp["error"]["type"]) logger_certbot.error("Could not obtain ZeroSSL credentials " + resp["error"]["type"])
os.environ['EASYHAPROXY_CERTBOT_SERVER'] = env_vars["certbot"]["server"] os.environ['EASYHAPROXY_CERTBOT_SERVER'] = env_vars["certbot"]["server"]
@ -131,7 +131,7 @@ class Functions:
@staticmethod @staticmethod
def setup_log(source): def setup_log(source):
level = os.getenv("%s_LOG_LEVEL" % (source.name.upper()), "").upper() level = os.getenv(f"{source.name.upper()}_LOG_LEVEL", "").upper()
level_importance = { level_importance = {
Functions.TRACE: logging.DEBUG, Functions.TRACE: logging.DEBUG,
Functions.DEBUG: logging.DEBUG, Functions.DEBUG: logging.DEBUG,
@ -192,7 +192,7 @@ class Functions:
return [return_code, output] return [return_code, output]
except Exception as e: except Exception as e:
log_source.error("%s" % e) log_source.error(f"{e}")
return [-99, e] return [-99, e]
@ -226,19 +226,19 @@ class DaemonizeHAProxy:
def get_haproxy_command(self, action, pid_file="/run/haproxy.pid"): def get_haproxy_command(self, action, pid_file="/run/haproxy.pid"):
custom_config_files = "" custom_config_files = ""
if len(list(self.get_custom_config_files().keys())) != 0: if len(list(self.get_custom_config_files().keys())) != 0:
custom_config_files = "-f %s" % self.custom_config_folder custom_config_files = f"-f {self.custom_config_folder}"
if action == DaemonizeHAProxy.HAPROXY_START or not os.path.exists(pid_file): if action == DaemonizeHAProxy.HAPROXY_START or not os.path.exists(pid_file):
return "/usr/sbin/haproxy -W -f /etc/haproxy/haproxy.cfg %s -p %s -S /var/run/haproxy.sock" % (custom_config_files, pid_file) return f"/usr/sbin/haproxy -W -f /etc/haproxy/haproxy.cfg {custom_config_files} -p {pid_file} -S /var/run/haproxy.sock"
else: else:
return_code, output = Functions().run_bash(loggerHaproxy, "cat %s" % pid_file, log_output=False) return_code, output = Functions().run_bash(logger_haproxy, f"cat {pid_file}", log_output=False)
pid = "".join(output).rstrip() pid = "".join(output).rstrip()
if psutil.pid_exists(int(pid)): if psutil.pid_exists(int(pid)):
return "/usr/sbin/haproxy -W -f /etc/haproxy/haproxy.cfg %s -p %s -x /var/run/haproxy.sock -sf %s" % (custom_config_files, pid_file, pid) return f"/usr/sbin/haproxy -W -f /etc/haproxy/haproxy.cfg {custom_config_files} -p {pid_file} -x /var/run/haproxy.sock -sf {pid}"
else: else:
os.unlink(pid_file) os.unlink(pid_file)
loggerHaproxy.warning( logger_haproxy.warning(
"PID file %s does not exist. Restarting haproxy instead of reload." % pid_file f"PID file {pid_file} does not exist. Restarting haproxy instead of reload."
) )
return self.get_haproxy_command(DaemonizeHAProxy.HAPROXY_START, pid_file) return self.get_haproxy_command(DaemonizeHAProxy.HAPROXY_START, pid_file)
@ -247,7 +247,7 @@ class DaemonizeHAProxy:
command = shlex.split(command) command = shlex.split(command)
try: try:
loggerHaproxy.debug("HAPROXY command: %s" % command) logger_haproxy.debug(f"HAPROXY command: {command}")
self.process = subprocess.Popen(command, self.process = subprocess.Popen(command,
shell=False, shell=False,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
@ -256,19 +256,19 @@ class DaemonizeHAProxy:
universal_newlines=True) universal_newlines=True)
except Exception as e: except Exception as e:
loggerHaproxy.error("%s" % e) logger_haproxy.error(f"{e}")
def __start(self): def __start(self):
try: try:
with self.process.stdout: with self.process.stdout:
for line in iter(self.process.stdout.readline, b''): for line in iter(self.process.stdout.readline, b''):
loggerHaproxy.info(line.rstrip()) logger_haproxy.info(line.rstrip())
return_code = self.process.wait() return_code = self.process.wait()
loggerHaproxy.debug("Return code %s" % return_code) logger_haproxy.debug(f"Return code {return_code}")
except Exception as e: except Exception as e:
loggerHaproxy.error("%s" % e) logger_haproxy.error(f"{e}")
def is_alive(self): def is_alive(self):
return self.thread.is_alive() return self.thread.is_alive()
@ -329,14 +329,14 @@ class Certbot:
@staticmethod @staticmethod
def set_eab_kid(eab_kid): def set_eab_kid(eab_kid):
if eab_kid != "": if eab_kid != "":
return "--eab-kid \"%s\"" % eab_kid return f'--eab-kid "{eab_kid}"'
else: else:
return "" return ""
@staticmethod @staticmethod
def set_eab_hmac_key(eab_hmac_key): def set_eab_hmac_key(eab_hmac_key):
if eab_hmac_key != "": if eab_hmac_key != "":
return "--eab-hmac-key \"%s\"" % eab_hmac_key return f'--eab-hmac-key "{eab_hmac_key}"'
else: else:
return "" return ""
@ -349,19 +349,19 @@ class Certbot:
renew_certs = [] renew_certs = []
for host in hosts: for host in hosts:
cert_status = self.get_certificate_status(host) cert_status = self.get_certificate_status(host)
host_arg = '-d %s' % host host_arg = f'-d {host}'
if cert_status == "ok" or cert_status == "error": if cert_status == "ok" or cert_status == "error":
continue continue
elif host in self.freeze_issue: elif host in self.freeze_issue:
freeze_count = self.freeze_issue.pop(host, 0) freeze_count = self.freeze_issue.pop(host, 0)
if freeze_count > 0: if freeze_count > 0:
loggerCertbot.debug("Waiting freezing period (%d) for %s due previous errors" % (freeze_count, host)) logger_certbot.debug(f"Waiting freezing period ({freeze_count}) for {host} due previous errors")
self.freeze_issue[host] = freeze_count-1 self.freeze_issue[host] = freeze_count-1
elif cert_status == "not_found" or cert_status == "expired": elif cert_status == "not_found" or cert_status == "expired":
loggerCertbot.debug("[%s] Request new certificate for %s" % (cert_status, host)) logger_certbot.debug(f"[{cert_status}] Request new certificate for {host}")
request_certs.append(host_arg) request_certs.append(host_arg)
elif cert_status == "expiring": elif cert_status == "expiring":
loggerCertbot.debug("[%s] Renew certificate for %s" % (cert_status, host)) logger_certbot.debug(f"[{cert_status}] Renew certificate for {host}")
renew_certs.append(host_arg) renew_certs.append(host_arg)
certbot_certonly = ('/usr/bin/certbot certonly {acme_server}' certbot_certonly = ('/usr/bin/certbot certonly {acme_server}'
@ -388,20 +388,20 @@ class Certbot:
if self.certbot_manual_auth_hook: if self.certbot_manual_auth_hook:
certbot_certonly += f' --manual --manual-auth-hook \'{self.certbot_manual_auth_hook}\'' certbot_certonly += f' --manual --manual-auth-hook \'{self.certbot_manual_auth_hook}\''
if loggerCertbot.level == logging.DEBUG: if logger_certbot.level == logging.DEBUG:
certbot_certonly += ' -v' certbot_certonly += ' -v'
loggerCertbot.debug("certbot_certonly: %s" % certbot_certonly) logger_certbot.debug(f"certbot_certonly: {certbot_certonly}")
ret_reload = False ret_reload = False
return_code_issue = 0 return_code_issue = 0
return_code_renew = 0 return_code_renew = 0
if len(request_certs) > 0: if len(request_certs) > 0:
return_code_issue, output = Functions.run_bash(loggerCertbot, certbot_certonly, return_result=False) return_code_issue, output = Functions.run_bash(logger_certbot, certbot_certonly, return_result=False)
ret_reload = True ret_reload = True
if len(renew_certs) > 0: if len(renew_certs) > 0:
return_code_renew, output = Functions.run_bash(loggerCertbot, "/usr/bin/certbot renew", return_result=False) return_code_renew, output = Functions.run_bash(logger_certbot, "/usr/bin/certbot renew", return_result=False)
ret_reload = True ret_reload = True
if ret_reload: if ret_reload:
@ -414,7 +414,7 @@ class Certbot:
return ret_reload return ret_reload
except Exception as e: except Exception as e:
loggerCertbot.error("%s" % e) logger_certbot.error(f"{e}")
return False return False
@staticmethod @staticmethod
@ -430,12 +430,12 @@ class Certbot:
if os.path.isdir(path): if os.path.isdir(path):
cert = Functions.load(os.path.join(path, "cert.pem")) cert = Functions.load(os.path.join(path, "cert.pem"))
key = Functions.load(os.path.join(path, "privkey.pem")) key = Functions.load(os.path.join(path, "privkey.pem"))
filename = "%s/%s.pem" % (self.certs, item) filename = f"{self.certs}/{item}.pem"
self.merge_certificate(cert, key, filename) self.merge_certificate(cert, key, filename)
def get_certificate_status(self, host): def get_certificate_status(self, host):
current_time = time.time() current_time = time.time()
filename = "%s/%s.pem" % (self.certs, host) filename = f"{self.certs}/{host}.pem"
if not os.path.exists(filename): if not os.path.exists(filename):
return "not_found" return "not_found"
@ -449,7 +449,7 @@ class Certbot:
elif (expiration_after - current_time) // (24 * 3600) <= 15: elif (expiration_after - current_time) // (24 * 3600) <= 15:
return "expiring" return "expiring"
except Exception as e: except Exception as e:
loggerCertbot.error("Certificate %s error %s" % (host, e)) logger_certbot.error(f"Certificate {host} error {e}")
return "error" return "error"
return "ok" return "ok"
@ -461,7 +461,7 @@ class Certbot:
cert_status = self.get_certificate_status(host) cert_status = self.get_certificate_status(host)
if cert_status != "ok": if cert_status != "ok":
self.freeze_issue[host] = self.retry_count self.freeze_issue[host] = self.retry_count
loggerCertbot.debug("Freeze issuing ssl for %s due failure. The certificate is %s" % (host, cert_status)) logger_certbot.debug(f"Freeze issuing ssl for {host} due failure. The certificate is {cert_status}")
@ -497,11 +497,11 @@ class SingleLineNonEmptyFilter(logging.Filter):
# #################################################################################################################### # ####################################################################################################################
# Setup Global Log # Setup Global Log
loggerInit = logging.getLogger(Functions.INIT_LOG) logger_init = logging.getLogger(Functions.INIT_LOG)
loggerHaproxy = logging.getLogger(Functions.HAPROXY_LOG) logger_haproxy = logging.getLogger(Functions.HAPROXY_LOG)
loggerEasyHaproxy = logging.getLogger(Functions.EASYHAPROXY_LOG) logger_easyhaproxy = logging.getLogger(Functions.EASYHAPROXY_LOG)
loggerCertbot = logging.getLogger(Functions.CERTBOT_LOG) logger_certbot = logging.getLogger(Functions.CERTBOT_LOG)
Functions.setup_log(loggerInit) Functions.setup_log(logger_init)
Functions.setup_log(loggerHaproxy) Functions.setup_log(logger_haproxy)
Functions.setup_log(loggerEasyHaproxy) Functions.setup_log(logger_easyhaproxy)
Functions.setup_log(loggerCertbot) Functions.setup_log(logger_certbot)

View file

@ -7,8 +7,8 @@ from functions import (
Consts, Consts,
DaemonizeHAProxy, DaemonizeHAProxy,
Functions, Functions,
loggerEasyHaproxy, logger_easyhaproxy,
loggerInit, logger_init,
) )
from processor import ProcessorInterface from processor import ProcessorInterface
@ -24,8 +24,8 @@ def start():
processor_obj.save_config(Consts.haproxy_config) processor_obj.save_config(Consts.haproxy_config)
processor_obj.save_certs(Consts.certs_haproxy) processor_obj.save_certs(Consts.certs_haproxy)
certbot_certs_found = processor_obj.get_certbot_hosts() certbot_certs_found = processor_obj.get_certbot_hosts()
loggerEasyHaproxy.info('Found hosts: %s' % ", ".join(processor_obj.get_hosts())) # Needs to run after save_config logger_easyhaproxy.info(f'Found hosts: {", ".join(processor_obj.get_hosts())}') # Needs to run after save_config
loggerEasyHaproxy.debug('Object Found: %s' % (processor_obj.get_parsed_object())) logger_easyhaproxy.debug(f'Object Found: {processor_obj.get_parsed_object()}')
old_haproxy = None old_haproxy = None
haproxy = DaemonizeHAProxy() haproxy = DaemonizeHAProxy()
@ -43,12 +43,12 @@ def start():
old_parsed = processor_obj.get_parsed_object() old_parsed = processor_obj.get_parsed_object()
processor_obj.refresh() processor_obj.refresh()
if certbot.check_certificates(certbot_certs_found) or DeepDiff(old_parsed, processor_obj.get_parsed_object()) != {} or not haproxy.is_alive() or DeepDiff(current_custom_config_files, haproxy.get_custom_config_files()) != {}: if certbot.check_certificates(certbot_certs_found) or DeepDiff(old_parsed, processor_obj.get_parsed_object()) != {} or not haproxy.is_alive() or DeepDiff(current_custom_config_files, haproxy.get_custom_config_files()) != {}:
loggerEasyHaproxy.info('New configuration found. Reloading...') logger_easyhaproxy.info('New configuration found. Reloading...')
loggerEasyHaproxy.debug('Object Found: %s' % (processor_obj.get_parsed_object())) logger_easyhaproxy.debug(f'Object Found: {processor_obj.get_parsed_object()}')
processor_obj.save_config(Consts.haproxy_config) processor_obj.save_config(Consts.haproxy_config)
processor_obj.save_certs(Consts.certs_haproxy) processor_obj.save_certs(Consts.certs_haproxy)
certbot_certs_found = processor_obj.get_certbot_hosts() certbot_certs_found = processor_obj.get_certbot_hosts()
loggerEasyHaproxy.info('Found hosts: %s' % ", ".join(processor_obj.get_hosts())) # Needs to after save_config logger_easyhaproxy.info(f'Found hosts: {", ".join(processor_obj.get_hosts())}') # Needs to after save_config
old_haproxy = haproxy old_haproxy = haproxy
haproxy = DaemonizeHAProxy() haproxy = DaemonizeHAProxy()
current_custom_config_files = haproxy.get_custom_config_files() current_custom_config_files = haproxy.get_custom_config_files()
@ -56,26 +56,26 @@ def start():
old_haproxy.terminate() old_haproxy.terminate()
except Exception as e: except Exception as e:
loggerEasyHaproxy.fatal("Err: %s" % e) logger_easyhaproxy.fatal(f"Err: {e}")
loggerEasyHaproxy.info('Heartbeat') logger_easyhaproxy.info('Heartbeat')
haproxy.sleep() haproxy.sleep()
def main(): def main():
Functions.run_bash(loggerInit, '/usr/sbin/haproxy -v') Functions.run_bash(logger_init, '/usr/sbin/haproxy -v')
loggerInit.info(" _ ") logger_init.info(" _ ")
loggerInit.info(" ___ __ _ ____ _ ___| |_ __ _ _ __ _ _ _____ ___ _ ") logger_init.info(" ___ __ _ ____ _ ___| |_ __ _ _ __ _ _ _____ ___ _ ")
loggerInit.info("/ -_) _` (_-< || |___| ' \\/ _` | '_ \\ '_/ _ \\ \\ / || |") logger_init.info("/ -_) _` (_-< || |___| ' \\/ _` | '_ \\ '_/ _ \\ \\ / || |")
loggerInit.info("\\___\\__,_/__/\\_, | |_||_\\__,_| .__/_| \\___/_\\_\\_, |") logger_init.info("\\___\\__,_/__/\\_, | |_||_\\__,_| .__/_| \\___/_\\_\\_, |")
loggerInit.info(" |__/ |_| |__/ ") logger_init.info(" |__/ |_| |__/ ")
loggerInit.info("Release: %s" % (os.getenv("RELEASE_VERSION"))) logger_init.info(f"Release: {os.getenv('RELEASE_VERSION')}")
loggerInit.debug('Environment:') logger_init.debug('Environment:')
for name, value in os.environ.items(): for name, value in os.environ.items():
if "HAPROXY" in name: if "HAPROXY" in name:
loggerInit.debug(f"- {name}: {value}") logger_init.debug(f"- {name}: {value}")
start() start()

View file

@ -4,9 +4,9 @@ import sys
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum
from typing import Any, Dict, List, Optional from typing import Any
from functions import loggerEasyHaproxy from functions import logger_easyhaproxy
class PluginType(Enum): class PluginType(Enum):
@ -89,7 +89,7 @@ class PluginManager:
self.plugins: dict[str, PluginInterface] = {} self.plugins: dict[str, PluginInterface] = {}
self.global_plugins: list[PluginInterface] = [] self.global_plugins: list[PluginInterface] = []
self.domain_plugins: list[PluginInterface] = [] self.domain_plugins: list[PluginInterface] = []
self.logger = loggerEasyHaproxy self.logger = logger_easyhaproxy
def load_plugins(self) -> None: def load_plugins(self) -> None:
""" """

View file

@ -29,7 +29,7 @@ import time
# Add parent directory to path for imports # Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from functions import loggerEasyHaproxy from functions import logger_easyhaproxy
from plugins import PluginContext, PluginInterface, PluginResult, PluginType from plugins import PluginContext, PluginInterface, PluginResult, PluginType
@ -66,7 +66,7 @@ class CleanupPlugin(PluginInterface):
try: try:
self.max_idle_time = int(config["max_idle_time"]) self.max_idle_time = int(config["max_idle_time"])
except ValueError: except ValueError:
loggerEasyHaproxy.warning(f"Invalid max_idle_time value: {config['max_idle_time']}, using default") logger_easyhaproxy.warning(f"Invalid max_idle_time value: {config['max_idle_time']}, using default")
if "cleanup_temp_files" in config: if "cleanup_temp_files" in config:
self.cleanup_temp_files = str(config["cleanup_temp_files"]).lower() in ["true", "1", "yes"] self.cleanup_temp_files = str(config["cleanup_temp_files"]).lower() in ["true", "1", "yes"]
@ -104,15 +104,15 @@ class CleanupPlugin(PluginInterface):
if file_age > self.max_idle_time: if file_age > self.max_idle_time:
os.remove(filepath) os.remove(filepath)
cleanup_actions.append(f"Removed old temp file: {filepath}") cleanup_actions.append(f"Removed old temp file: {filepath}")
loggerEasyHaproxy.debug(f"Cleanup plugin: Removed {filepath}") logger_easyhaproxy.debug(f"Cleanup plugin: Removed {filepath}")
except Exception as e: except Exception as e:
loggerEasyHaproxy.warning(f"Failed to remove temp file {filepath}: {e}") logger_easyhaproxy.warning(f"Failed to remove temp file {filepath}: {e}")
except Exception as e: except Exception as e:
loggerEasyHaproxy.warning(f"Failed to cleanup {temp_dir}: {e}") logger_easyhaproxy.warning(f"Failed to cleanup {temp_dir}: {e}")
# Log cleanup summary # Log cleanup summary
if cleanup_actions: if cleanup_actions:
loggerEasyHaproxy.info(f"Cleanup plugin: Performed {len(cleanup_actions)} cleanup action(s)") logger_easyhaproxy.info(f"Cleanup plugin: Performed {len(cleanup_actions)} cleanup action(s)")
return PluginResult( return PluginResult(
haproxy_config="", # No HAProxy config needed for cleanup haproxy_config="", # No HAProxy config needed for cleanup

View file

@ -33,7 +33,7 @@ import sys
# Add parent directory to path for imports # Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from functions import loggerEasyHaproxy from functions import logger_easyhaproxy
from plugins import PluginContext, PluginInterface, PluginResult, PluginType from plugins import PluginContext, PluginInterface, PluginResult, PluginType
@ -127,9 +127,9 @@ class CloudflarePlugin(PluginInterface):
for ip_range in self.CLOUDFLARE_IPS: for ip_range in self.CLOUDFLARE_IPS:
f.write(f"{ip_range}\n") f.write(f"{ip_range}\n")
loggerEasyHaproxy.info(f"Cloudflare plugin: Written {len(self.CLOUDFLARE_IPS)} IP ranges to {self.ip_list_path}") logger_easyhaproxy.info(f"Cloudflare plugin: Written {len(self.CLOUDFLARE_IPS)} IP ranges to {self.ip_list_path}")
except Exception as e: except Exception as e:
loggerEasyHaproxy.warning(f"Cloudflare plugin: Failed to write IP list to {self.ip_list_path}: {e}") logger_easyhaproxy.warning(f"Cloudflare plugin: Failed to write IP list to {self.ip_list_path}: {e}")
# Generate HAProxy config snippet # Generate HAProxy config snippet
haproxy_config = f"""# Cloudflare - Restore original visitor IP haproxy_config = f"""# Cloudflare - Restore original visitor IP

View file

@ -74,7 +74,7 @@ import sys
# Add parent directory to path for imports # Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from functions import loggerEasyHaproxy from functions import logger_easyhaproxy
from plugins import PluginContext, PluginInterface, PluginResult, PluginType from plugins import PluginContext, PluginInterface, PluginResult, PluginType
@ -180,7 +180,7 @@ class JwtValidatorPlugin(PluginInterface):
domain_safe = context.domain.replace(".", "_").replace(":", "_") domain_safe = context.domain.replace(".", "_").replace(":", "_")
pubkey_file = f"/etc/haproxy/jwt_keys/{domain_safe}_pubkey.pem" pubkey_file = f"/etc/haproxy/jwt_keys/{domain_safe}_pubkey.pem"
else: else:
loggerEasyHaproxy.warning(f"JWT validator plugin for {context.domain}: No pubkey or pubkey_path configured") logger_easyhaproxy.warning(f"JWT validator plugin for {context.domain}: No pubkey or pubkey_path configured")
return PluginResult() return PluginResult()
# Build HAProxy configuration # Build HAProxy configuration

View file

@ -8,7 +8,7 @@ from kubernetes import client, config
from kubernetes.client.rest import ApiException from kubernetes.client.rest import ApiException
from easymapping import HaproxyConfigGenerator from easymapping import HaproxyConfigGenerator
from functions import Consts, ContainerEnv, Functions, loggerEasyHaproxy from functions import Consts, ContainerEnv, Functions, logger_easyhaproxy
class ProcessorInterface: class ProcessorInterface:
@ -42,7 +42,7 @@ class ProcessorInterface:
elif mode == ProcessorInterface.KUBERNETES: elif mode == ProcessorInterface.KUBERNETES:
return Kubernetes() return Kubernetes()
else: else:
loggerEasyHaproxy.fatal("Expected mode to be 'static', 'docker', 'swarm' or 'kubernetes'. I got '%s'" % mode) logger_easyhaproxy.fatal(f"Expected mode to be 'static', 'docker', 'swarm' or 'kubernetes'. I got '{mode}'")
return None return None
def refresh(self): def refresh(self):
@ -110,7 +110,7 @@ class Static(ProcessorInterface):
if "hosts" not in obj: if "hosts" not in obj:
continue continue
for host in obj["hosts"].keys(): for host in obj["hosts"].keys():
hosts.append("%s:%s" % (host, obj["port"])) hosts.append(f"{host}:{obj['port']}")
return hosts return hosts
def parse(self): def parse(self):
@ -152,7 +152,7 @@ class Docker(ProcessorInterface):
try: try:
ha_proxy_network_name = next( ha_proxy_network_name = next(
iter(self.client.containers.get(socket.gethostname()).attrs["NetworkSettings"]["Networks"])) iter(self.client.containers.get(socket.gethostname()).attrs["NetworkSettings"]["Networks"]))
except: except Exception:
# HAProxy is not running in a container, get first container network # HAProxy is not running in a container, get first container network
if len(self.client.containers.list()) == 0: if len(self.client.containers.list()) == 0:
return return
@ -236,7 +236,6 @@ class Kubernetes(ProcessorInterface):
Returns: tuple (mode: str, service: V1Service or None) Returns: tuple (mode: str, service: V1Service or None)
""" """
import os import os
import time
# Return cached if available # Return cached if available
if self.deployment_mode_cache: if self.deployment_mode_cache:
@ -246,7 +245,7 @@ class Kubernetes(ProcessorInterface):
# Check for manual override # Check for manual override
if env_config['deployment_mode'] != 'auto': if env_config['deployment_mode'] != 'auto':
loggerEasyHaproxy.info(f"Using manual deployment mode: {env_config['deployment_mode']}") logger_easyhaproxy.info(f"Using manual deployment mode: {env_config['deployment_mode']}")
service = self._get_easyhaproxy_service() if env_config['deployment_mode'] in ['nodeport', 'clusterip'] else None service = self._get_easyhaproxy_service() if env_config['deployment_mode'] in ['nodeport', 'clusterip'] else None
self.deployment_mode_cache = (env_config['deployment_mode'], service) self.deployment_mode_cache = (env_config['deployment_mode'], service)
return self.deployment_mode_cache return self.deployment_mode_cache
@ -264,7 +263,7 @@ class Kubernetes(ProcessorInterface):
owner_kind = pod.metadata.owner_references[0].kind owner_kind = pod.metadata.owner_references[0].kind
if owner_kind == 'DaemonSet': if owner_kind == 'DaemonSet':
loggerEasyHaproxy.info("Detected deployment mode: daemonset") logger_easyhaproxy.info("Detected deployment mode: daemonset")
self.deployment_mode_cache = ('daemonset', None) self.deployment_mode_cache = ('daemonset', None)
return self.deployment_mode_cache return self.deployment_mode_cache
elif owner_kind in ['ReplicaSet', 'Deployment']: elif owner_kind in ['ReplicaSet', 'Deployment']:
@ -272,15 +271,15 @@ class Kubernetes(ProcessorInterface):
service = self._get_easyhaproxy_service() service = self._get_easyhaproxy_service()
if service: if service:
if service.spec.type == 'NodePort': if service.spec.type == 'NodePort':
loggerEasyHaproxy.info("Detected deployment mode: nodeport") logger_easyhaproxy.info("Detected deployment mode: nodeport")
self.deployment_mode_cache = ('nodeport', service) self.deployment_mode_cache = ('nodeport', service)
return self.deployment_mode_cache return self.deployment_mode_cache
else: else:
loggerEasyHaproxy.info("Detected deployment mode: clusterip") logger_easyhaproxy.info("Detected deployment mode: clusterip")
self.deployment_mode_cache = ('clusterip', service) self.deployment_mode_cache = ('clusterip', service)
return self.deployment_mode_cache return self.deployment_mode_cache
except Exception as e: except Exception as e:
loggerEasyHaproxy.warn(f"Failed to detect deployment mode: {e}, defaulting to daemonset") logger_easyhaproxy.warn(f"Failed to detect deployment mode: {e}, defaulting to daemonset")
self.deployment_mode_cache = ('daemonset', None) self.deployment_mode_cache = ('daemonset', None)
return self.deployment_mode_cache return self.deployment_mode_cache
@ -298,11 +297,11 @@ class Kubernetes(ProcessorInterface):
try: try:
service = self.api_instance.read_namespaced_service(service_name, namespace) service = self.api_instance.read_namespaced_service(service_name, namespace)
return service return service
except: except Exception:
continue continue
return None return None
except Exception as e: except Exception as e:
loggerEasyHaproxy.warn(f"Failed to get EasyHAProxy service: {e}") logger_easyhaproxy.warn(f"Failed to get EasyHAProxy service: {e}")
return None return None
def _get_ingress_addresses(self, mode, service): def _get_ingress_addresses(self, mode, service):
@ -385,7 +384,7 @@ class Kubernetes(ProcessorInterface):
addresses.append({"ip": service.spec.cluster_ip}) addresses.append({"ip": service.spec.cluster_ip})
except Exception as e: except Exception as e:
loggerEasyHaproxy.warn(f"Failed to get ingress addresses: {e}") logger_easyhaproxy.warn(f"Failed to get ingress addresses: {e}")
# Cache the result # Cache the result
self.ingress_addresses_cache = addresses self.ingress_addresses_cache = addresses
@ -422,13 +421,13 @@ class Kubernetes(ProcessorInterface):
field_manager="easyhaproxy" field_manager="easyhaproxy"
) )
loggerEasyHaproxy.debug( logger_easyhaproxy.debug(
f"Updated ingress {ingress.metadata.namespace}/{ingress.metadata.name} " f"Updated ingress {ingress.metadata.namespace}/{ingress.metadata.name} "
f"status with {len(addresses)} address(es)" f"status with {len(addresses)} address(es)"
) )
except Exception as e: except Exception as e:
loggerEasyHaproxy.warn( logger_easyhaproxy.warn(
f"Failed to update status for ingress " f"Failed to update status for ingress "
f"{ingress.metadata.namespace}/{ingress.metadata.name}: {e}" f"{ingress.metadata.namespace}/{ingress.metadata.name}: {e}"
) )
@ -508,37 +507,37 @@ class Kubernetes(ProcessorInterface):
ssl_hosts.extend(tls.hosts) ssl_hosts.extend(tls.hosts)
except Exception as e: except Exception as e:
loggerEasyHaproxy.warn("Ingress %s - Get secret failed: '%s'" % (ingress_name, e)) logger_easyhaproxy.warn(f"Ingress {ingress_name} - Get secret failed: '{e}'")
loggerEasyHaproxy.debug("Ingress %s - SSL Hosts found '%s'" % (ingress_name, ssl_hosts)) logger_easyhaproxy.debug(f"Ingress {ingress_name} - SSL Hosts found '{ssl_hosts}'")
for rule in ingress.spec.rules: for rule in ingress.spec.rules:
rule_data = {} rule_data = {}
port_number = rule.http.paths[0].backend.service.port.number port_number = rule.http.paths[0].backend.service.port.number
definition = "easyhaproxy.%s_%s" % (rule.host.replace(".", "-"), port_number) definition = f"easyhaproxy.{rule.host.replace('.', '-')}_{port_number}"
rule_data["%s.host" % definition] = rule.host rule_data[f"{definition}.host"] = rule.host
rule_data["%s.port" % definition] = listen_port rule_data[f"{definition}.port"] = listen_port
rule_data["%s.localport" % definition] = port_number rule_data[f"{definition}.localport"] = port_number
if rule.host in ssl_hosts: if rule.host in ssl_hosts:
rule_data["%s.clone_to_ssl" % definition] = 'true' rule_data[f"{definition}.clone_to_ssl"] = 'true'
if redirect_ssl is not None: if redirect_ssl is not None:
rule_data["%s.redirect_ssl" % definition] = redirect_ssl rule_data[f"{definition}.redirect_ssl"] = redirect_ssl
if certbot is not None: if certbot is not None:
rule_data["%s.certbot" % definition] = certbot rule_data[f"{definition}.certbot"] = certbot
if redirect is not None: if redirect is not None:
rule_data["%s.redirect" % definition] = redirect rule_data[f"{definition}.redirect"] = redirect
if mode is not None: if mode is not None:
rule_data["%s.mode" % definition] = mode rule_data[f"{definition}.mode"] = mode
rule_data["%s.balance" % definition] = self._check_annotation(ingress.metadata.annotations, "easyhaproxy.balance", "roundrobin") rule_data[f"{definition}.balance"] = self._check_annotation(ingress.metadata.annotations, "easyhaproxy.balance", "roundrobin")
# Add plugin configuration # Add plugin configuration
if plugins is not None: if plugins is not None:
rule_data["%s.plugins" % definition] = plugins rule_data[f"{definition}.plugins"] = plugins
# Add plugin-specific configurations # Add plugin-specific configurations
for plugin_key, plugin_value in plugin_annotations.items(): for plugin_key, plugin_value in plugin_annotations.items():
# Convert easyhaproxy.plugin.X.Y to easyhaproxy.{definition}.plugin.X.Y # Convert easyhaproxy.plugin.X.Y to easyhaproxy.{definition}.plugin.X.Y
plugin_config_key = plugin_key.replace("easyhaproxy.plugin.", "%s.plugin." % definition) plugin_config_key = plugin_key.replace("easyhaproxy.plugin.", f"{definition}.plugin.")
rule_data[plugin_config_key] = plugin_value rule_data[plugin_config_key] = plugin_value
service_name = rule.http.paths[0].backend.service.name service_name = rule.http.paths[0].backend.service.name
@ -547,7 +546,7 @@ class Kubernetes(ProcessorInterface):
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
loggerEasyHaproxy.warn("Ingress %s - Service %s - Failed: '%s'" % (ingress_name, service_name, e)) logger_easyhaproxy.warn(f"Ingress {ingress_name} - Service {service_name} - Failed: '{e}'")
if cluster_ip is not None: if cluster_ip is not None:
if cluster_ip not in self.parsed_object.keys(): if cluster_ip not in self.parsed_object.keys():

View file

@ -54,4 +54,4 @@ def test_daemonize_haproxy2_check_config():
def test_daemonize_haproxy2_get_haproxy_command_start(): def test_daemonize_haproxy2_get_haproxy_command_start():
daemon = DaemonizeHAProxy(os.path.abspath(os.path.dirname(__file__)) + '/fixtures') daemon = DaemonizeHAProxy(os.path.abspath(os.path.dirname(__file__)) + '/fixtures')
command = daemon.get_haproxy_command(DaemonizeHAProxy.HAPROXY_START) command = daemon.get_haproxy_command(DaemonizeHAProxy.HAPROXY_START)
assert command == "/usr/sbin/haproxy -W -f /etc/haproxy/haproxy.cfg -f %s -p /run/haproxy.pid -S /var/run/haproxy.sock" % (os.path.dirname(__file__) + "/fixtures") assert command == f"/usr/sbin/haproxy -W -f /etc/haproxy/haproxy.cfg -f {os.path.dirname(__file__)}/fixtures -p /run/haproxy.pid -S /var/run/haproxy.sock"

View file

@ -4,41 +4,41 @@ import random
import string import string
from io import StringIO from io import StringIO
from functions import Functions, loggerCertbot, loggerEasyHaproxy, loggerHaproxy from functions import Functions, logger_certbot, logger_easyhaproxy, logger_haproxy
log_stream = StringIO() # Create StringIO object log_stream = StringIO() # Create StringIO object
log_handler = logging.StreamHandler(log_stream) log_handler = logging.StreamHandler(log_stream)
log_formatter = logging.Formatter('%(levelname)s - %(message)s') log_formatter = logging.Formatter('%(levelname)s - %(message)s')
log_handler.setFormatter(log_formatter) log_handler.setFormatter(log_formatter)
loggerDebug = logging.getLogger(__name__) logger_debug = logging.getLogger(__name__)
loggerDebug.setLevel(logging.DEBUG) logger_debug.setLevel(logging.DEBUG)
loggerDebug.addHandler(log_handler) logger_debug.addHandler(log_handler)
def test_functions_check_local_level(): def test_functions_check_local_level():
assert Functions.setup_log(loggerCertbot) == logging.INFO assert Functions.setup_log(logger_certbot) == logging.INFO
assert Functions.setup_log(loggerHaproxy) == logging.INFO assert Functions.setup_log(logger_haproxy) == logging.INFO
assert Functions.setup_log(loggerEasyHaproxy) == logging.INFO assert Functions.setup_log(logger_easyhaproxy) == logging.INFO
os.environ['CERTBOT_LOG_LEVEL'] = 'warn' os.environ['CERTBOT_LOG_LEVEL'] = 'warn'
assert Functions.setup_log(loggerCertbot) == logging.WARNING assert Functions.setup_log(logger_certbot) == logging.WARNING
del os.environ['CERTBOT_LOG_LEVEL'] del os.environ['CERTBOT_LOG_LEVEL']
os.environ['HAPROXY_LOG_LEVEL'] = 'warn' os.environ['HAPROXY_LOG_LEVEL'] = 'warn'
assert Functions.setup_log(loggerHaproxy) == logging.WARNING assert Functions.setup_log(logger_haproxy) == logging.WARNING
del os.environ['HAPROXY_LOG_LEVEL'] del os.environ['HAPROXY_LOG_LEVEL']
os.environ['EASYHAPROXY_LOG_LEVEL'] = 'warn' os.environ['EASYHAPROXY_LOG_LEVEL'] = 'warn'
assert Functions.setup_log(loggerEasyHaproxy) == logging.WARNING assert Functions.setup_log(logger_easyhaproxy) == logging.WARNING
del os.environ['EASYHAPROXY_LOG_LEVEL'] del os.environ['EASYHAPROXY_LOG_LEVEL']
def test_function_load_and_save(): def test_function_load_and_save():
filename = '/tmp/x.txt' filename = '/tmp/x.txt'
try: try:
assert os.path.exists(filename) == False assert not os.path.exists(filename)
text = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(50)) text = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(50))
Functions.save(filename, text) Functions.save(filename, text)
assert os.path.exists(filename) == True assert os.path.exists(filename)
assert Functions.load(filename) == text assert Functions.load(filename) == text
finally: finally:
os.unlink(filename) os.unlink(filename)
@ -46,7 +46,7 @@ def test_function_load_and_save():
def test_functions_run_bash_log_output(): def test_functions_run_bash_log_output():
print() print()
try: try:
return_code, result = Functions.run_bash(loggerDebug, "echo 'test run 1'", log_output=True, return_code, result = Functions.run_bash(logger_debug, "echo 'test run 1'", log_output=True,
return_result=False) return_result=False)
assert return_code == 0 assert return_code == 0
assert result == [] assert result == []
@ -60,7 +60,7 @@ def test_functions_run_bash_log_output():
def test_functions_run_bash_no_log_output(): def test_functions_run_bash_no_log_output():
print() print()
try: try:
return_code, result = Functions.run_bash(loggerDebug, "echo 'test run 2'", log_output=False, return_code, result = Functions.run_bash(logger_debug, "echo 'test run 2'", log_output=False,
return_result=False) return_result=False)
assert return_code == 0 assert return_code == 0
assert result == [] assert result == []
@ -72,7 +72,7 @@ def test_functions_run_bash_no_log_output():
def test_functions_run_bash_return(): def test_functions_run_bash_return():
print() print()
try: try:
return_code, result = Functions.run_bash(loggerDebug, "echo 'test run 3'", log_output=False, return_code, result = Functions.run_bash(logger_debug, "echo 'test run 3'", log_output=False,
return_result=True) return_result=True)
assert return_code == 0 assert return_code == 0
assert len(log_stream.getvalue()) == 0 assert len(log_stream.getvalue()) == 0
@ -84,7 +84,7 @@ def test_functions_run_bash_return():
def test_functions_run_bash_log_and_return_output(): def test_functions_run_bash_log_and_return_output():
print() print()
try: try:
return_code, result = Functions.run_bash(loggerDebug, "echo 'test run 4'", return_code, result = Functions.run_bash(logger_debug, "echo 'test run 4'",
log_output=True, log_output=True,
return_result=True) return_result=True)
assert return_code == 0 assert return_code == 0
@ -99,7 +99,7 @@ def test_functions_run_bash_log_and_return_output():
def test_functions_run_bash_ok(): def test_functions_run_bash_ok():
print() print()
try: try:
return_code, result = Functions.run_bash(loggerDebug, "%s/fixtures/run_bash.sh" % os.path.dirname(__file__), return_code, result = Functions.run_bash(logger_debug, f"{os.path.dirname(__file__)}/fixtures/run_bash.sh",
log_output=True, log_output=True,
return_result=False) return_result=False)
assert return_code == 0 assert return_code == 0
@ -114,7 +114,7 @@ def test_functions_run_bash_ok():
def test_functions_run_bash_fail(): def test_functions_run_bash_fail():
print() print()
try: try:
return_code, result = Functions.run_bash(loggerDebug, "%s/fixtures/run_bash.sh 15" % os.path.dirname(__file__), return_code, result = Functions.run_bash(logger_debug, f"{os.path.dirname(__file__)}/fixtures/run_bash.sh 15",
log_output=True, log_output=True,
return_result=False) return_result=False)
assert return_code == 15 assert return_code == 15
@ -129,7 +129,7 @@ def test_functions_run_bash_fail():
def test_functions_run_command_not_found(): def test_functions_run_command_not_found():
print() print()
try: try:
return_code, result = Functions.run_bash(loggerDebug, "no_command_here", return_code, result = Functions.run_bash(logger_debug, "no_command_here",
log_output=True, log_output=True,
return_result=False) return_result=False)
assert return_code == -99 assert return_code == -99