refactor: migrate data storage from JSON/map files to SQLite
Replace servers.json, certificates.json, and map file parsing with SQLite (WAL mode) as single source of truth. HAProxy map files are now generated from SQLite via sync_map_files(). Key changes: - Add db.py with schema, connection management, and JSON migration - Add DB_FILE config constant - Delegate file_ops.py functions to db.py - Refactor domains.py to use file_ops instead of direct list manipulation - Fix subprocess.TimeoutExpired not caught (doesn't inherit TimeoutError) - Add DB health check in health.py - Init DB on startup in server.py and __main__.py - Update all 359 tests to use SQLite-backed functions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""Certificate management tools for HAProxy MCP Server."""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
from typing import Annotated
|
||||
|
||||
@@ -152,7 +153,7 @@ def _haproxy_list_certs_impl() -> str:
|
||||
certs.append(f"• {domain} ({ca})\n Created: {created}\n Renew: {renew}\n Status: {status}")
|
||||
|
||||
return "\n\n".join(certs) if certs else "No certificates found"
|
||||
except TimeoutError:
|
||||
except (TimeoutError, subprocess.TimeoutExpired):
|
||||
return "Error: Command timed out"
|
||||
except FileNotFoundError:
|
||||
return "Error: acme.sh not found"
|
||||
@@ -203,7 +204,7 @@ def _haproxy_cert_info_impl(domain: str) -> str:
|
||||
result.stdout.strip()
|
||||
]
|
||||
return "\n".join(info)
|
||||
except TimeoutError:
|
||||
except (TimeoutError, subprocess.TimeoutExpired):
|
||||
return "Error: Command timed out"
|
||||
except OSError as e:
|
||||
logger.error("Error getting certificate info for %s: %s", domain, e)
|
||||
@@ -250,7 +251,7 @@ def _haproxy_issue_cert_impl(domain: str, wildcard: bool) -> str:
|
||||
else:
|
||||
return f"Certificate issued but PEM file not created. Check {host_path}"
|
||||
|
||||
except TimeoutError:
|
||||
except (TimeoutError, subprocess.TimeoutExpired):
|
||||
return f"Error: Certificate issuance timed out after {CERT_TIMEOUT}s"
|
||||
except OSError as e:
|
||||
logger.error("Error issuing certificate for %s: %s", domain, e)
|
||||
@@ -289,7 +290,7 @@ def _haproxy_renew_cert_impl(domain: str, force: bool) -> str:
|
||||
else:
|
||||
return f"Error renewing certificate:\n{output}"
|
||||
|
||||
except TimeoutError:
|
||||
except (TimeoutError, subprocess.TimeoutExpired):
|
||||
return f"Error: Certificate renewal timed out after {CERT_TIMEOUT}s"
|
||||
except FileNotFoundError:
|
||||
return "Error: acme.sh not found"
|
||||
@@ -323,7 +324,7 @@ def _haproxy_renew_all_certs_impl() -> str:
|
||||
else:
|
||||
return "Renewal check completed"
|
||||
|
||||
except TimeoutError:
|
||||
except (TimeoutError, subprocess.TimeoutExpired):
|
||||
return "Error: Renewal cron timed out"
|
||||
except FileNotFoundError:
|
||||
return "Error: acme.sh not found"
|
||||
|
||||
Reference in New Issue
Block a user