Add haproxy_cleanup_wildcards tool to remove subdomain wildcard entries
New db_remove_wildcard() for surgical wildcard-only deletion. New haproxy_cleanup_wildcards tool scans all wildcard entries and removes those belonging to subdomains (e.g., *.nocodb.inouter.com) while keeping base domain wildcards (e.g., *.anvil.it.com). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -355,6 +355,21 @@ def db_remove_domain(domain: str) -> None:
|
|||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def db_remove_wildcard(domain: str) -> bool:
|
||||||
|
"""Remove only the wildcard entry for a domain from the database.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
domain: Base domain name (without leading dot, e.g., "nocodb.inouter.com").
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if a wildcard entry was deleted, False if not found.
|
||||||
|
"""
|
||||||
|
conn = get_connection()
|
||||||
|
cur = conn.execute("DELETE FROM domains WHERE domain = ? AND is_wildcard = 1", (f".{domain}",))
|
||||||
|
conn.commit()
|
||||||
|
return cur.rowcount > 0
|
||||||
|
|
||||||
|
|
||||||
def db_find_available_pool() -> Optional[str]:
|
def db_find_available_pool() -> Optional[str]:
|
||||||
"""Find the first available pool not assigned to any domain.
|
"""Find the first available pool not assigned to any domain.
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ from ..file_ops import (
|
|||||||
remove_domain_from_map,
|
remove_domain_from_map,
|
||||||
find_available_pool,
|
find_available_pool,
|
||||||
)
|
)
|
||||||
from ..db import db_load_certs
|
from ..db import db_load_certs, db_remove_wildcard, sync_map_files
|
||||||
from ..utils import parse_servers_state, disable_server_slot
|
from ..utils import parse_servers_state, disable_server_slot
|
||||||
|
|
||||||
|
|
||||||
@@ -408,3 +408,48 @@ def register_domain_tools(mcp):
|
|||||||
return f"Error: Failed to update map file: {e}"
|
return f"Error: Failed to update map file: {e}"
|
||||||
except HaproxyError as e:
|
except HaproxyError as e:
|
||||||
return f"Error: {e}"
|
return f"Error: {e}"
|
||||||
|
|
||||||
|
@mcp.tool()
|
||||||
|
def haproxy_cleanup_wildcards() -> str:
|
||||||
|
"""Remove unnecessary wildcard entries for subdomain domains.
|
||||||
|
|
||||||
|
Scans all wildcard entries and removes those where the domain is a
|
||||||
|
subdomain (not a base domain). Base domains keep their wildcards.
|
||||||
|
|
||||||
|
Example: *.nocodb.inouter.com is removed (subdomain of inouter.com),
|
||||||
|
but *.anvil.it.com is kept (anvil.it.com is a base domain).
|
||||||
|
"""
|
||||||
|
entries = get_map_contents()
|
||||||
|
|
||||||
|
# Build registered domains set
|
||||||
|
registered_domains: set[str] = set()
|
||||||
|
for entry_domain, _ in entries:
|
||||||
|
if not entry_domain.startswith("."):
|
||||||
|
registered_domains.add(entry_domain)
|
||||||
|
|
||||||
|
# Find wildcard entries that should be removed
|
||||||
|
removed = []
|
||||||
|
for entry_domain, backend in entries:
|
||||||
|
if not entry_domain.startswith("."):
|
||||||
|
continue
|
||||||
|
domain = entry_domain[1:] # strip leading dot
|
||||||
|
is_sub, parent = _check_subdomain(domain, registered_domains)
|
||||||
|
if is_sub:
|
||||||
|
# Remove from DB
|
||||||
|
if db_remove_wildcard(domain):
|
||||||
|
# Remove from HAProxy runtime map
|
||||||
|
try:
|
||||||
|
haproxy_cmd(f"del map {WILDCARDS_MAP_FILE_CONTAINER} {entry_domain}")
|
||||||
|
except HaproxyError as e:
|
||||||
|
logger.warning("Failed to remove wildcard map entry %s: %s", entry_domain, e)
|
||||||
|
removed.append(f"{entry_domain} -> {backend} (subdomain of {parent})")
|
||||||
|
|
||||||
|
if removed:
|
||||||
|
# Sync map files from DB
|
||||||
|
sync_map_files()
|
||||||
|
result = f"Removed {len(removed)} unnecessary wildcard(s):\n"
|
||||||
|
result += "\n".join(f" • {r}" for r in removed)
|
||||||
|
else:
|
||||||
|
result = "No unnecessary wildcard entries found."
|
||||||
|
|
||||||
|
return result
|
||||||
|
|||||||
Reference in New Issue
Block a user