refactor: Improve code quality, error handling, and test coverage

- Add file_lock context manager to eliminate duplicate locking patterns
- Add ValidationError, ConfigurationError, CertificateError exceptions
- Improve rollback logic in haproxy_add_servers (track successful ops only)
- Decompose haproxy_add_domain into smaller helper functions
- Consolidate certificate constants (CERTS_DIR, ACME_HOME) to config.py
- Enhance docstrings for internal functions and magic numbers
- Add pytest framework with 48 new tests (269 -> 317 total)
- Increase test coverage from 76% to 86%
  - servers.py: 58% -> 82%
  - certificates.py: 67% -> 86%
  - configuration.py: 69% -> 94%

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kaffa
2026-02-03 12:50:00 +09:00
parent 18ce812920
commit 6bcfee519c
25 changed files with 6852 additions and 125 deletions

View File

@@ -89,13 +89,45 @@ def haproxy_cmd_checked(command: str) -> str:
def _check_response_for_errors(response: str) -> None:
"""Check HAProxy response for error indicators.
"""Check HAProxy response for error indicators and raise if found.
HAProxy Runtime API returns plain text responses. Success responses are
typically empty or contain requested data. Error responses contain
specific keywords that indicate the command failed.
Args:
response: Response string from HAProxy
response: Response string from HAProxy Runtime API command.
Raises:
HaproxyError: If response contains error indicators
HaproxyError: If response contains any error indicator keyword.
Error Indicators:
- "No such": Resource doesn't exist (e.g., backend, server, map entry)
- "not found": Similar to "No such", resource lookup failed
- "error": General error in command execution
- "failed": Operation could not be completed
- "invalid": Malformed command or invalid parameter value
- "unknown": Unrecognized command or parameter
Examples:
Successful responses (will NOT raise):
- "" (empty string for successful set commands)
- "1" (map entry ID after successful add)
- Server state data (for show commands)
Error responses (WILL raise HaproxyError):
- "No such server." - Server doesn't exist in specified backend
- "No such backend." - Backend name not found
- "No such map." - Map file not loaded or doesn't exist
- "Entry not found." - Map entry lookup failed
- "Invalid server state." - Bad state value for set server state
- "unknown keyword 'xyz'" - Unrecognized command parameter
- "failed to allocate memory" - Resource allocation failure
- "'set server' expects <addr>:<port>" - Invalid command syntax
Note:
The check is case-insensitive to catch variations like "Error:",
"ERROR:", "error:" etc. that HAProxy may return.
"""
error_indicators = ["No such", "not found", "error", "failed", "invalid", "unknown"]
if response: