#!/bin/bash # Entrypoint script para Cisco MAC Monitor # ======================================== set -e # Colores para output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Función para logging log() { echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" } error() { echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ERROR:${NC} $1" >&2 } warn() { echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] WARNING:${NC} $1" } success() { echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] SUCCESS:${NC} $1" } # Verificar archivo de configuración check_config() { if [[ ! -f "${CONFIG_FILE}" ]]; then error "Archivo de configuración no encontrado: ${CONFIG_FILE}" error "Asegúrese de montar el volumen /config con config.yaml" exit 1 fi log "Usando archivo de configuración: ${CONFIG_FILE}" } # Crear directorios necesarios setup_directories() { log "Configurando directorios..." # Crear directorios si no existen mkdir -p /logs /data /tmp # Verificar permisos if [[ ! -w /logs ]]; then warn "Sin permisos de escritura en /logs, usando /tmp" export LOG_DIR=/tmp else export LOG_DIR=/logs fi if [[ ! -w /data ]]; then warn "Sin permisos de escritura en /data, usando /tmp" export DATA_DIR=/tmp else export DATA_DIR=/data fi success "Directorios configurados correctamente" } # Validar conectividad de red test_network() { log "Verificando conectividad de red..." # Verificar si podemos resolver DNS if ! nslookup google.com > /dev/null 2>&1; then warn "No se puede resolver DNS externo, verificando conectividad local..." fi # Extraer IPs de dispositivos del config para test básico if command -v python3 > /dev/null 2>&1 && [[ -f "${CONFIG_FILE}" ]]; then python3 -c " import yaml try: with open('${CONFIG_FILE}', 'r') as f: config = yaml.safe_load(f) for device in config.get('devices', []): ip = device.get('ip') if ip: print(f'Testing connectivity to {ip}...') import subprocess result = subprocess.run(['ping', '-c', '1', '-W', '3', ip], capture_output=True, timeout=5) if result.returncode == 0: print(f'✓ {ip} reachable') else: print(f'✗ {ip} not reachable') except Exception as e: print(f'Error testing network connectivity: {e}') " fi } # Función para mostrar ayuda show_help() { cat << EOF Cisco MAC Monitor - Contenedor Docker USAGE: docker run cisco-mac-monitor [COMMAND] [OPTIONS] COMMANDS: continuous Ejecutar monitorización continua (por defecto) single-run Ejecutar una sola vez y salir test-config Validar archivo de configuración test-ssh Probar conexiones SSH a dispositivos shell Abrir shell interactivo help Mostrar esta ayuda VARIABLES DE ENTORNO: CONFIG_FILE Ruta al archivo de configuración (default: /config/config.yaml) LOG_LEVEL Nivel de logging (default: INFO) MONITORING_INTERVAL Intervalo de monitorización en minutos (default: 5) VOLÚMENES: /config Directorio de configuración (contiene config.yaml) /logs Directorio de logs /data Directorio de datos de salida EJEMPLOS: # Ejecutar monitorización continua docker run -v /host/config:/config cisco-mac-monitor # Ejecutar una sola vez docker run -v /host/config:/config cisco-mac-monitor single-run # Probar configuración docker run -v /host/config:/config cisco-mac-monitor test-config EOF } # Función para probar configuración test_config() { log "Validando configuración..." if ! python3 -c " import yaml import sys try: with open('${CONFIG_FILE}', 'r') as f: config = yaml.safe_load(f) # Validar estructura básica if 'devices' not in config: print('ERROR: Sección devices no encontrada') sys.exit(1) if 'monitoring' not in config: print('ERROR: Sección monitoring no encontrada') sys.exit(1) # Validar dispositivos devices = config['devices'] if not devices: print('ERROR: No hay dispositivos configurados') sys.exit(1) print(f'✓ Configuración válida: {len(devices)} dispositivos') for i, device in enumerate(devices): hostname = device.get('hostname', f'device-{i}') ip = device.get('ip') username = device.get('username') if not ip: print(f'ERROR: Device {hostname} sin IP') sys.exit(1) if not username: print(f'ERROR: Device {hostname} sin username') sys.exit(1) print(f' - {hostname} ({ip})') except Exception as e: print(f'ERROR: {e}') sys.exit(1) "; then error "Configuración inválida" exit 1 fi success "Configuración válida" } # Función para probar conexiones SSH test_ssh() { log "Probando conexiones SSH a dispositivos..." python3 << EOF import yaml import paramiko import sys try: with open('${CONFIG_FILE}', 'r') as f: config = yaml.safe_load(f) devices = config.get('devices', []) success_count = 0 for device in devices: hostname = device.get('hostname', 'unknown') ip = device.get('ip') username = device.get('username') password = device.get('password') port = device.get('port', 22) print(f'Probando {hostname} ({ip})...', end=' ') try: ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect( hostname=ip, port=port, username=username, password=password, timeout=10, look_for_keys=False, allow_agent=False ) ssh.close() print('✓ CONECTADO') success_count += 1 except Exception as e: print(f'✗ ERROR: {e}') print(f'\\nResultado: {success_count}/{len(devices)} dispositivos conectados') if success_count == 0: sys.exit(1) except Exception as e: print(f'ERROR: {e}') sys.exit(1) EOF } # Función principal main() { log "Iniciando Cisco MAC Monitor..." # Configurar directorios setup_directories # Verificar configuración check_config # Procesar comando COMMAND=${1:-continuous} case "${COMMAND}" in "continuous") log "Modo: Monitorización continua" test_config warn "Iniciando monitorización continua - Presiona Ctrl+C para detener" exec python3 /app/cisco_mac_monitor.py --config "${CONFIG_FILE}" ;; "single-run") log "Modo: Ejecución única" test_config exec python3 /app/cisco_mac_monitor.py --config "${CONFIG_FILE}" --single-run --output "${DATA_DIR}/cisco_mac_data.json" ;; "test-config") test_config success "Configuración OK" ;; "test-ssh") test_config test_ssh ;; "test-network") test_network ;; "shell") log "Abriendo shell interactivo..." exec /bin/bash ;; "help"|"--help"|"-h") show_help ;; *) error "Comando desconocido: ${COMMAND}" show_help exit 1 ;; esac } # Manejo de señales trap 'log "Recibida señal de terminación, cerrando..."; exit 0' SIGTERM SIGINT # Ejecutar función principal main "$@"