#!/bin/bash # ============================================================================== # validate-ports.sh - Validacion de puertos contra registry # ============================================================================== # Uso: ./validate-ports.sh [directorio-a-validar] # ============================================================================== set -e # Colores RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # Rutas SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" CONTROL_PLANE="${SCRIPT_DIR}/../../.." REGISTRY="${CONTROL_PLANE}/registries/ports.registry.yml" echo -e "${YELLOW}=== Validando puertos contra registry ===${NC}" echo "Registry: $REGISTRY" # Verificar que existe el registry if [ ! -f "$REGISTRY" ]; then echo -e "${RED}ERROR: Registry no encontrado: $REGISTRY${NC}" exit 1 fi # Funcion para extraer puertos del registry get_allowed_ports() { python3 << 'EOF' import yaml import sys registry_path = sys.argv[1] if len(sys.argv) > 1 else 'ports.registry.yml' with open(registry_path, 'r') as f: data = yaml.safe_load(f) ports = set() # Infraestructura for svc, config in data.get('infrastructure', {}).items(): if isinstance(config, dict): if 'internal' in config: ports.add(config['internal']) if 'public' in config: if isinstance(config['public'], list): ports.update(config['public']) else: ports.add(config['public']) # Dashboard y otros internos if isinstance(config.get('internal'), dict): for k, v in config['internal'].items(): if isinstance(v, int): ports.add(v) # Proyectos for proj, proj_config in data.get('projects', {}).items(): if isinstance(proj_config, dict): for svc, svc_config in proj_config.get('services', {}).items(): if isinstance(svc_config, dict) and 'internal' in svc_config: ports.add(svc_config['internal']) for p in sorted(ports): print(p) EOF } # Funcion para buscar puertos en compose files find_compose_ports() { local search_path="${1:-.}" # Buscar puertos en formato "XXXX:XXXX" o "- XXXX" grep -rhoE '(- "|ports:.*")[0-9]{4,5}(:|")' "$search_path" \ --include="docker-compose*.yml" \ --include="compose*.yml" 2>/dev/null | \ grep -oE '[0-9]{4,5}' | sort -u || true } # Obtener puertos permitidos echo "" echo -e "${YELLOW}Puertos registrados:${NC}" ALLOWED=$(get_allowed_ports "$REGISTRY") echo "$ALLOWED" | tr '\n' ' ' echo "" # Buscar en directorio especificado o repos/ SEARCH_DIR="${1:-${CONTROL_PLANE}/../repos}" if [ ! -d "$SEARCH_DIR" ]; then echo -e "${YELLOW}WARN: Directorio no existe: $SEARCH_DIR${NC}" echo "No hay archivos compose para validar" exit 0 fi echo "" echo -e "${YELLOW}Buscando puertos en: $SEARCH_DIR${NC}" ERRORS=0 WARNINGS=0 # Buscar puertos en uso USED=$(find_compose_ports "$SEARCH_DIR") if [ -z "$USED" ]; then echo "No se encontraron puertos en archivos compose" else echo "Puertos encontrados en compose files:" for port in $USED; do if echo "$ALLOWED" | grep -q "^${port}$"; then echo -e " ${GREEN}[OK]${NC} Puerto $port esta registrado" else echo -e " ${RED}[ERROR]${NC} Puerto $port NO esta en registry" ERRORS=$((ERRORS + 1)) fi done fi # Verificar conflictos (puertos duplicados) echo "" echo -e "${YELLOW}Verificando conflictos...${NC}" # Buscar todos los archivos compose y verificar puertos duplicados COMPOSE_FILES=$(find "$SEARCH_DIR" -name "docker-compose*.yml" -o -name "compose*.yml" 2>/dev/null || true) declare -A PORT_USAGE for file in $COMPOSE_FILES; do if [ -f "$file" ]; then PORTS_IN_FILE=$(grep -oE '- "[0-9]+:' "$file" 2>/dev/null | grep -oE '[0-9]+' || true) for port in $PORTS_IN_FILE; do if [ -n "${PORT_USAGE[$port]}" ]; then echo -e " ${RED}[CONFLICT]${NC} Puerto $port usado en multiple archivos:" echo " - ${PORT_USAGE[$port]}" echo " - $file" ERRORS=$((ERRORS + 1)) else PORT_USAGE[$port]="$file" fi done fi done # Resultado echo "" if [ $ERRORS -eq 0 ]; then echo -e "${GREEN}=== Validacion exitosa ===${NC}" exit 0 else echo -e "${RED}=== Validacion fallida: $ERRORS errores ===${NC}" exit 1 fi