Introduce embedded HTTP server for HAProxy monitoring dashboard
- Added a Python-based HTTP server to serve `dashboard.html` at `/` or `/dashboard.html` paths. - Updated HAProxy configuration to integrate backend for the dashboard. - Enhanced handling of index paths with conditional redirects to the dashboard page. - Modified tests and updated expected outputs to reflect these changes.
This commit is contained in:
parent
67cfcf3aff
commit
7e3134155a
16 changed files with 153 additions and 70 deletions
|
|
@ -2,6 +2,8 @@ import argparse
|
|||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import threading
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
|
||||
from deepdiff import DeepDiff
|
||||
|
||||
|
|
@ -16,6 +18,38 @@ from functions import (
|
|||
from processor import ProcessorInterface
|
||||
|
||||
|
||||
class DashboardHandler(BaseHTTPRequestHandler):
|
||||
_content: bytes | None = None
|
||||
|
||||
def do_GET(self):
|
||||
if self.path in ("/", "/index.html", "/dashboard.html"):
|
||||
if DashboardHandler._content is None:
|
||||
dashboard_path = os.path.join(Consts.www_path, "dashboard.html")
|
||||
try:
|
||||
with open(dashboard_path, "rb") as f:
|
||||
DashboardHandler._content = f.read()
|
||||
except OSError:
|
||||
DashboardHandler._content = b""
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "text/html; charset=utf-8")
|
||||
self.send_header("Content-Length", str(len(DashboardHandler._content)))
|
||||
self.end_headers()
|
||||
self.wfile.write(DashboardHandler._content)
|
||||
else:
|
||||
self.send_response(404)
|
||||
self.end_headers()
|
||||
|
||||
def log_message(self, format, *args):
|
||||
pass
|
||||
|
||||
|
||||
def start_dashboard_server():
|
||||
server = HTTPServer(("127.0.0.1", Consts.DASHBOARD_SERVER_PORT), DashboardHandler)
|
||||
t = threading.Thread(target=server.serve_forever, daemon=True)
|
||||
t.start()
|
||||
logger_easyhaproxy.info(f"Dashboard server listening on 127.0.0.1:{Consts.DASHBOARD_SERVER_PORT}")
|
||||
|
||||
|
||||
def _build_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="easy-haproxy",
|
||||
|
|
@ -146,6 +180,8 @@ def start():
|
|||
os.makedirs(Consts.certs_certbot, exist_ok=True)
|
||||
os.makedirs(Consts.certs_haproxy, exist_ok=True)
|
||||
|
||||
start_dashboard_server()
|
||||
|
||||
processor_obj.save_config(Consts.haproxy_config)
|
||||
processor_obj.save_certs(Consts.certs_haproxy)
|
||||
certbot_certs_found = processor_obj.get_certbot_hosts()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import re
|
|||
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
from functions import Functions, logger_easyhaproxy
|
||||
from functions import Functions, logger_easyhaproxy, Consts
|
||||
|
||||
from .label_handler import DockerLabelHandler
|
||||
|
||||
|
|
@ -92,7 +92,8 @@ class HaproxyConfigGenerator:
|
|||
return template.render(
|
||||
data=self.mapping,
|
||||
global_plugin_configs=self.global_plugin_configs,
|
||||
defaults_plugin_configs=self.defaults_plugin_configs
|
||||
defaults_plugin_configs=self.defaults_plugin_configs,
|
||||
dashboard_server_port=Consts.DASHBOARD_SERVER_PORT
|
||||
)
|
||||
|
||||
def parse(self, container_metadata):
|
||||
|
|
|
|||
|
|
@ -56,4 +56,11 @@ class Consts:
|
|||
@classproperty
|
||||
def certs_haproxy(cls):
|
||||
"""Path to user-provided certificates directory."""
|
||||
return f"{cls.base_path}/certs/haproxy"
|
||||
return f"{cls.base_path}/certs/haproxy"
|
||||
|
||||
@classproperty
|
||||
def www_path(cls):
|
||||
"""Path to the web assets directory (dashboard, static files)."""
|
||||
return f"{cls.base_path}/www"
|
||||
|
||||
DASHBOARD_SERVER_PORT = 9190
|
||||
|
|
@ -10,7 +10,7 @@ The plugin creates:
|
|||
|
||||
Configuration:
|
||||
- enabled: Enable/disable the plugin (default: true)
|
||||
- document_root: Document root path (default: /etc/easyhaproxy/www)
|
||||
- document_root: Document root path (default: /var/www/html)
|
||||
- script_filename: Pattern for SCRIPT_FILENAME (default: %[path])
|
||||
- index_file: Default index file (default: index.php)
|
||||
- path_info: Enable PATH_INFO support (default: true)
|
||||
|
|
@ -39,8 +39,6 @@ Example Kubernetes Annotation:
|
|||
import os
|
||||
import sys
|
||||
|
||||
from functions import Consts
|
||||
|
||||
# Add parent directory to path for imports
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
|
|
@ -52,7 +50,7 @@ class FastcgiPlugin(PluginInterface):
|
|||
|
||||
def __init__(self):
|
||||
self.enabled = True
|
||||
self.document_root = Consts.base_path + "/www"
|
||||
self.document_root = "/var/www/html"
|
||||
self.script_filename = "%[path]"
|
||||
self.index_file = "index.php"
|
||||
self.path_info = True
|
||||
|
|
|
|||
|
|
@ -97,8 +97,14 @@ frontend dashboard
|
|||
mode http
|
||||
acl is_index path /
|
||||
acl is_index path /index.html
|
||||
http-request return status 200 content-type "text/html" file /etc/easyhaproxy/www/dashboard.html if is_index
|
||||
http-request return status 404
|
||||
acl is_dashboard path /dashboard.html
|
||||
http-request set-path /dashboard.html if is_index
|
||||
http-request return status 404 if !is_dashboard
|
||||
default_backend srv_dashboard
|
||||
|
||||
backend srv_dashboard
|
||||
mode http
|
||||
server Local 127.0.0.1:{{ dashboard_server_port }}
|
||||
{% endif %}
|
||||
{% for o in data["easymapping"] -%}
|
||||
{% set mode = o["mode"] or "http" %}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue