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:
@@ -13,14 +13,12 @@ from ..config import (
|
||||
WILDCARDS_MAP_FILE_CONTAINER,
|
||||
POOL_COUNT,
|
||||
MAX_SLOTS,
|
||||
StateField,
|
||||
STATE_MIN_COLUMNS,
|
||||
SUBPROCESS_TIMEOUT,
|
||||
CERTS_DIR,
|
||||
logger,
|
||||
)
|
||||
from ..exceptions import HaproxyError
|
||||
from ..validation import validate_domain, validate_ip
|
||||
from ..validation import validate_domain, validate_ip, validate_port_int
|
||||
from ..haproxy_client import haproxy_cmd
|
||||
from ..file_ops import (
|
||||
get_map_contents,
|
||||
@@ -31,6 +29,7 @@ from ..file_ops import (
|
||||
remove_server_from_config,
|
||||
remove_domain_from_config,
|
||||
)
|
||||
from ..utils import parse_servers_state, disable_server_slot
|
||||
|
||||
|
||||
def _find_available_pool(entries: list[tuple[str, str]], used_pools: set[str]) -> Optional[str]:
|
||||
@@ -166,18 +165,18 @@ def register_domain_tools(mcp):
|
||||
try:
|
||||
domains = []
|
||||
state = haproxy_cmd("show servers state")
|
||||
parsed_state = parse_servers_state(state)
|
||||
|
||||
# Build server map from HAProxy state
|
||||
server_map: dict[str, list] = {}
|
||||
for line in state.split("\n"):
|
||||
parts = line.split()
|
||||
if len(parts) >= STATE_MIN_COLUMNS and parts[StateField.SRV_ADDR] != "0.0.0.0":
|
||||
backend = parts[StateField.BE_NAME]
|
||||
if backend not in server_map:
|
||||
server_map[backend] = []
|
||||
server_map[backend].append(
|
||||
f"{parts[StateField.SRV_NAME]}={parts[StateField.SRV_ADDR]}:{parts[StateField.SRV_PORT]}"
|
||||
)
|
||||
server_map: dict[str, list[str]] = {}
|
||||
for backend, servers_dict in parsed_state.items():
|
||||
for server_name, srv_info in servers_dict.items():
|
||||
if srv_info["addr"] != "0.0.0.0":
|
||||
if backend not in server_map:
|
||||
server_map[backend] = []
|
||||
server_map[backend].append(
|
||||
f"{server_name}={srv_info['addr']}:{srv_info['port']}"
|
||||
)
|
||||
|
||||
# Read from domains.map
|
||||
seen_domains: set[str] = set()
|
||||
@@ -220,7 +219,7 @@ def register_domain_tools(mcp):
|
||||
return "Error: Invalid domain format"
|
||||
if not validate_ip(ip, allow_empty=True):
|
||||
return "Error: Invalid IP address format"
|
||||
if not (1 <= http_port <= 65535):
|
||||
if not validate_port_int(http_port):
|
||||
return "Error: Port must be between 1 and 65535"
|
||||
|
||||
# Use file locking for the entire pool allocation operation
|
||||
@@ -339,8 +338,7 @@ def register_domain_tools(mcp):
|
||||
for slot in range(1, MAX_SLOTS + 1):
|
||||
server = f"{backend}_{slot}"
|
||||
try:
|
||||
haproxy_cmd(f"set server {backend}/{server} state maint")
|
||||
haproxy_cmd(f"set server {backend}/{server} addr 0.0.0.0 port 0")
|
||||
disable_server_slot(backend, server)
|
||||
except HaproxyError as e:
|
||||
logger.warning(
|
||||
"Failed to clear server %s/%s for domain %s: %s",
|
||||
|
||||
Reference in New Issue
Block a user