mirror of
https://github.com/taylanbakircioglu/haproxy-openmanager.git
synced 2026-09-20 09:33:29 +00:00
fix(config): robust use_backend_rules parsing with comprehensive type handling
PROBLEM: - Config generation was producing invalid syntax: use_backend ["..."] - HAProxy validation failing on agents - Old code had insufficient type checking for JSONB fields ROOT CAUSE: - Missing ELSE branch when use_backend_rules wasn't a list - No handling for unexpected types (tuple, Record, etc.) - No debug logging to track type issues FIX: - Added comprehensive type checking (str, list, tuple, other) - Added debug logging to track type and value - Added fallback parsing for string representation of lists - Enhanced validation to skip invalid entries - Prevents generation of invalid HAProxy syntax IMPACT: - Fixes validation failure for cluster 7 (demo-cluster) - Enables proper parsing of JSONB use_backend_rules - Backward compatible with legacy string format TESTED: - Database validation: use_backend_rules is proper JSONB array - String elements correctly extracted and written - Invalid types caught and logged
This commit is contained in:
committed by
taylanbakircioglu
parent
35dd8e5d13
commit
2dcdaeeba1
@@ -409,26 +409,58 @@ async def generate_haproxy_config_for_cluster(cluster_id: int, conn: Optional[An
|
||||
# Use Backend Rules
|
||||
if frontend.get('use_backend_rules'):
|
||||
use_backend_rules = frontend['use_backend_rules']
|
||||
# Parse JSON string if needed
|
||||
|
||||
# DEBUG: Log type and value
|
||||
logger.debug(f"Frontend '{frontend['name']}' use_backend_rules type: {type(use_backend_rules)}, value: {use_backend_rules}")
|
||||
|
||||
# Normalize to list
|
||||
rules_list = None
|
||||
|
||||
if isinstance(use_backend_rules, str):
|
||||
# String: try JSON parse first
|
||||
try:
|
||||
use_backend_rules = json.loads(use_backend_rules)
|
||||
parsed = json.loads(use_backend_rules)
|
||||
if isinstance(parsed, list):
|
||||
rules_list = parsed
|
||||
else:
|
||||
logger.warning(f"Frontend '{frontend['name']}' use_backend_rules parsed to non-list: {type(parsed)}")
|
||||
except:
|
||||
# Legacy format: newline-separated string
|
||||
use_backend_rules = [r.strip() for r in use_backend_rules.split('\n') if r.strip()]
|
||||
rules_list = [r.strip() for r in use_backend_rules.split('\n') if r.strip()]
|
||||
|
||||
if isinstance(use_backend_rules, list):
|
||||
for rule in use_backend_rules:
|
||||
if rule and rule.strip():
|
||||
elif isinstance(use_backend_rules, (list, tuple)):
|
||||
# Already a sequence
|
||||
rules_list = list(use_backend_rules)
|
||||
|
||||
else:
|
||||
# Unexpected type - try to convert to string and log warning
|
||||
logger.error(f"Frontend '{frontend['name']}' use_backend_rules has unexpected type {type(use_backend_rules)}: {use_backend_rules}")
|
||||
# Try to convert to string representation and parse
|
||||
try:
|
||||
rules_str = str(use_backend_rules)
|
||||
if rules_str.startswith('[') and rules_str.endswith(']'):
|
||||
# Looks like a string representation of a list
|
||||
rules_list = json.loads(rules_str)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to parse use_backend_rules: {e}")
|
||||
rules_list = None
|
||||
|
||||
# Write rules if we successfully parsed them
|
||||
if rules_list:
|
||||
for rule in rules_list:
|
||||
if rule and isinstance(rule, str):
|
||||
rule_text = rule.strip()
|
||||
# Skip empty strings, "[]", or invalid use_backend rules
|
||||
if rule_text and rule_text not in ('[]', '{}', 'null', 'None'):
|
||||
if rule_text and rule_text not in ('[]', '{}', 'null', 'None', '""', "''"):
|
||||
# CRITICAL FIX: use_backend rules from parser already include "use_backend" keyword
|
||||
# Don't add it again! Parser stores: "use_backend BackendName if condition"
|
||||
# If rule doesn't start with "use_backend ", add it (for manual entries)
|
||||
if not rule_text.startswith('use_backend '):
|
||||
rule_text = f"use_backend {rule_text}"
|
||||
config_lines.append(f" {rule_text}")
|
||||
logger.debug(f"Added use_backend rule: {rule_text}")
|
||||
else:
|
||||
logger.warning(f"Skipping invalid rule (type: {type(rule)}): {rule}")
|
||||
|
||||
# Default backend (already added at the beginning of frontend section)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user