refactor: Extract large functions, improve exception handling, remove duplicates
## Large function extraction - servers.py: Extract 8 _impl functions from register_server_tools (449 lines) - certificates.py: Extract 7 _impl functions from register_certificate_tools (386 lines) - MCP tool wrappers now delegate to module-level implementation functions ## Exception handling improvements - Replace 11 broad `except Exception` with specific types - health.py: (OSError, subprocess.SubprocessError) - configuration.py: (HaproxyError, IOError, OSError, ValueError) - servers.py: (IOError, OSError, ValueError) - certificates.py: FileNotFoundError, (subprocess.SubprocessError, OSError) ## Duplicate code extraction - Add parse_servers_state() to utils.py (replaces 4 duplicate parsers) - Add disable_server_slot() to utils.py (replaces duplicate patterns) - Update health.py, servers.py, domains.py to use new helpers ## Other improvements - Add TypedDict types in file_ops.py and health.py - Set file permissions (0o600) for sensitive files - Update tests to use specific exception types Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1078,9 +1078,10 @@ class TestLoadCertToHaproxyError:
|
||||
pem_file = certs_dir / "example.com.pem"
|
||||
pem_file.write_text("cert content")
|
||||
|
||||
# Mock haproxy_cmd to raise exception
|
||||
# Mock haproxy_cmd to raise HaproxyError
|
||||
from haproxy_mcp.exceptions import HaproxyError
|
||||
with patch("haproxy_mcp.tools.certificates.CERTS_DIR", str(certs_dir)):
|
||||
with patch("haproxy_mcp.tools.certificates.haproxy_cmd", side_effect=Exception("Connection failed")):
|
||||
with patch("haproxy_mcp.tools.certificates.haproxy_cmd", side_effect=HaproxyError("Connection failed")):
|
||||
from haproxy_mcp.tools.certificates import load_cert_to_haproxy
|
||||
|
||||
success, msg = load_cert_to_haproxy("example.com")
|
||||
|
||||
@@ -547,7 +547,7 @@ class TestStartupRestoreFailures:
|
||||
|
||||
with patch("socket.socket", return_value=mock_sock):
|
||||
with patch("haproxy_mcp.tools.configuration.restore_servers_from_config", return_value=0):
|
||||
with patch("haproxy_mcp.tools.certificates.restore_certificates", side_effect=Exception("Certificate error")):
|
||||
with patch("haproxy_mcp.tools.certificates.restore_certificates", side_effect=IOError("Certificate error")):
|
||||
with caplog.at_level(logging.WARNING, logger="haproxy_mcp"):
|
||||
from haproxy_mcp.tools.configuration import startup_restore
|
||||
|
||||
@@ -598,7 +598,7 @@ class TestHaproxyReloadFailures:
|
||||
|
||||
with patch("socket.socket", return_value=mock_sock):
|
||||
with patch("haproxy_mcp.haproxy_client.reload_haproxy", return_value=(True, "Reloaded")):
|
||||
with patch("haproxy_mcp.tools.configuration.restore_servers_from_config", side_effect=Exception("Restore failed")):
|
||||
with patch("haproxy_mcp.tools.configuration.restore_servers_from_config", side_effect=OSError("Restore failed")):
|
||||
with patch("time.sleep", return_value=None):
|
||||
from haproxy_mcp.tools.configuration import register_config_tools
|
||||
mcp = MagicMock()
|
||||
|
||||
@@ -756,8 +756,8 @@ class TestHaproxyAddServersRollback:
|
||||
|
||||
def mock_configure_server_slot(backend, server_prefix, slot, ip, http_port):
|
||||
if slot == 2:
|
||||
# Simulate unexpected error (not HaproxyError)
|
||||
raise RuntimeError("Unexpected system error")
|
||||
# Simulate unexpected error (IOError is caught by the exception handler)
|
||||
raise IOError("Unexpected system error")
|
||||
configured_slots.append(slot)
|
||||
return f"{server_prefix}_{slot}"
|
||||
|
||||
@@ -807,7 +807,7 @@ class TestHaproxyAddServersRollback:
|
||||
|
||||
def mock_configure_server_slot(backend, server_prefix, slot, ip, http_port):
|
||||
if slot == 2:
|
||||
raise RuntimeError("Unexpected error")
|
||||
raise OSError("Unexpected error")
|
||||
return f"{server_prefix}_{slot}"
|
||||
|
||||
def mock_remove_server_from_config(domain, slot):
|
||||
|
||||
Reference in New Issue
Block a user