Commit Graph

11 Commits

Author SHA1 Message Date
kaffa
4a411202d3 feat: Add pool sharing for domains
Allow multiple domains to share the same backend pool using share_with parameter.
This saves pool slots when domains point to the same servers.

- Add share_with parameter to haproxy_add_domain
- Add helper functions for shared domain management
- Protect shared pools from being cleared on domain removal
- Update documentation with pool sharing examples

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 00:34:22 +09:00
kaffa
95ab0583b3 docs: Simplify verbose docstrings
- save_map_file(): 55 lines → 12 lines
- is_legacy_backend(): 42 lines → 11 lines
- _check_response_for_errors(): 40 lines → 9 lines

Keep essential info, remove redundant examples and explanations.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 13:25:45 +09:00
kaffa
06ab47aca8 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>
2026-02-03 13:23:51 +09:00
kaffa
6bcfee519c 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>
2026-02-03 12:50:00 +09:00
kaffa
18ce812920 perf: Implement 2-stage map routing for faster domain lookup
Split domain routing into two stages for improved performance:
- Stage 1: map_str for exact domains (O(log n) using ebtree)
- Stage 2: map_dom for wildcards only (O(n) but small set)

Wildcards now stored in separate wildcards.map file.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:46:04 +09:00
kaffa
46c86b62f2 fix: HAProxy batch commands and improve routing/subdomain handling
- Fix haproxy_cmd_batch to send each command on separate connection
  (HAProxy Runtime API only processes first command on single connection)
- HTTP frontend now routes to backends instead of redirecting to HTTPS
- Add subdomain detection to avoid duplicate wildcard entries
- Add reload verification with retry logic
- Optimize SSL: TLS 1.3 ciphersuites, extended session lifetime
- Add CPU steal monitoring script

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:46:04 +09:00
kaffa
6ced2b42d4 refactor: Move certificate config functions to file_ops.py
- Move load_certs_config, save_certs_config, add_cert_to_config,
  remove_cert_from_config from certificates.py to file_ops.py
- Add CERTS_FILE constant to config.py
- Add file locking for certificate config operations (was missing)
- Consistent pattern with servers.json handling

certificates.py: 543 → 503 lines
file_ops.py: 263 → 337 lines

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 04:26:55 +00:00
kaffa
79254835e9 feat: Zero-downtime certificate management via Runtime API
Changes:
- Replace USR2 signal reload with HAProxy Runtime API for cert updates
  - new ssl cert → set ssl cert → commit ssl cert
  - No connection drops during certificate changes
- Add certificates.json for persistence (domain list only)
- Add haproxy_load_cert tool for manual certificate loading
- Auto-restore certificates on MCP startup
- Update startup sequence to load both servers and certificates

certificates.json format:
{
  "domains": ["inouter.com", "anvil.it.com"]
}

Paths derived from convention:
- Host: /opt/haproxy/certs/{domain}.pem
- Container: /etc/haproxy/certs/{domain}.pem

Total MCP tools: 28 → 29

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 04:23:28 +00:00
kaffa
7ebe204f89 feat: Add certificate coverage check to haproxy_add_domain
When adding a domain, now checks if an SSL certificate covers it:
- Exact match: domain.com.pem
- Wildcard match: parent.com.pem with *.parent.com SAN

Output examples:
- "SSL: Using certificate inouter.com (wildcard)"
- "SSL: No certificate found. Use haproxy_issue_cert(...) to issue one."

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 04:15:02 +00:00
kaffa
dbacb86d60 feat: Add certificate management tools (6 new MCP tools)
New tools for SSL/TLS certificate management via acme.sh:
- haproxy_list_certs: List all certificates with expiry info
- haproxy_cert_info: Get detailed certificate info (expiry, issuer, SANs)
- haproxy_issue_cert: Issue new certificate via Cloudflare DNS validation
- haproxy_renew_cert: Renew specific certificate (with force option)
- haproxy_renew_all_certs: Renew all certificates due for renewal
- haproxy_delete_cert: Delete certificate from acme.sh and HAProxy

Features:
- Automatic PEM deployment to HAProxy certs directory
- HAProxy hot-reload after certificate changes (USR2 signal)
- Cloudflare DNS validation with CF_Token support
- Wildcard certificate support

Total MCP tools: 22 → 28

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 03:55:26 +00:00
kaffa
7bee373684 refactor: Modularize MCP server with command batching
- Split monolithic mcp/server.py (1874 lines) into haproxy_mcp/ package:
  - config.py: Configuration constants and environment variables
  - exceptions.py: Custom exception classes
  - validation.py: Input validation functions
  - haproxy_client.py: HAProxy Runtime API client with batch support
  - file_ops.py: Atomic file operations with locking
  - utils.py: CSV parsing utilities
  - tools/: MCP tools organized by function
    - domains.py: Domain management (3 tools)
    - servers.py: Server management (7 tools)
    - health.py: Health checks (3 tools)
    - monitoring.py: Monitoring (4 tools)
    - configuration.py: Config management (4 tools)

- Add haproxy_cmd_batch() for sending multiple commands in single TCP connection
- Optimize server operations: 1 connection instead of 2 per server
- Optimize startup restore: All servers in 1 connection (was 2×N)
- Update type hints to Python 3.9+ style (built-in generics)
- Remove unused imports and functions
- Update CLAUDE.md with new structure and performance notes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 03:50:42 +00:00