# frozen_string_literal: true # adn/tools/core/nodos_info.rb — Utilidades para extracción de metadatos de fichas de nodos # ====================================================================================== require_relative 'constants' module ADN module NodosInfo def self.extraer_metadata(nodo_nombre) ruta = File.join(ADN::NODOS_DIR, "#{nodo_nombre}.md") return nil unless File.exist?(ruta) contenido = File.read(ruta, encoding: 'UTF-8') { nombre: nodo_nombre, ip: detectar_ip(contenido), host: detectar_host(contenido), so: detectar_so(contenido), vmid: detectar_vmid(contenido), puerto_ssh: detectar_puerto_ssh(contenido) || 22, usuario: detectar_usuario(contenido), clave_boveda: detectar_clave_boveda(contenido), auth_type: detectar_auth_type(contenido) } end def self.detectar_usuario(contenido) # **SSH**: user@ip:port o DOMAIN\user@ip:port if contenido =~ /\*\*SSH\*\*:\s*`?([^`\s(]+)/i full = $1 # Extraer usuario de formato user@ip:port o DOMAIN\user@ip:port if full.include?('@') return full.split('@')[0...-1].join('@') if full.split('@').last =~ /^[\d\.]+/ return full.split(':')[0] end return full end # Fallback: | SSH | user@domain@ip:7022 | if contenido =~ /(?:SSH|Acceso)\*\*?:?\s*`?([a-zA-Z0-9_\-\.\\@]+)/i full = $1 if full.include?('@') parts = full.split('@') if parts.last =~ /^\d{1,3}(\.\d{1,3}){3}/ return parts[0...-1].join('@') else return full.split(':')[0] end end return full end nil end def self.detectar_ip(contenido) # Prioridad 1: IP de línea SSH (es la IP operativa para conexión) if contenido =~ /\*\*SSH\*\*:\s*`?[^@]+@([\d\.]+)/i return $1 end # | IP / Ubicación | 10.0.10.10 | # | IP | 10.0.100.11/24 | if contenido =~ /\|\s*IP\s*(?:\/\s*Ubicación)?\s*\|\s*`?([\d\.]+)/i return $1 end # - **IP**: `10.0.10.200` if contenido =~ /IP\*\*:\s*`?([\d\.]+)/i return $1 end nil end def self.detectar_host(contenido) if contenido =~ /\*\*(?:Padre\/Host|Host Anfitrión|Anfitrión|Host)\*\*\s*[:\|]?\s*`?([a-zA-Z0-9\-]+)`?/i return $1 end nil end def self.detectar_so(contenido) # | Sistema Operativo | ... | o - **Sistema Operativo**: ... if contenido =~ /(?:\||\-)\s*\*\*?(?:Sistema Operativo|SO|OS)\*\*?\s*[:\|]\s*([^\|\n]+)/i so_raw = $1.strip return :windows if so_raw =~ /windows|server|win/i return :linux if so_raw =~ /linux|ubuntu|debian|centos|rocky|proxmox/i end :linux # Default end def self.detectar_vmid(contenido) if contenido =~ /(?:VM ID|vmid|VMID)\*\*?:?\s*`?(\d+)`?/i return $1 end nil end def self.detectar_puerto_ssh(contenido) # **SSH**: user@ip:7022 if contenido =~ /\*\*SSH\*\*:\s*`?[^`\s]+:(\d+)/i return $1.to_i end # | SSH | user@ip:7022 | if contenido =~ /(?:SSH|Puerto|Puerto SSH)\*\*?:?\s*.*:(\d+)/i return $1.to_i end # (Puerto 7022) if contenido =~ /\(Puerto\s+(\d+)\)/i return $1.to_i end nil end # Detecta la clave de la bóveda de candados desde la ficha # Formato esperado: (Bóveda: `clave`) o (Bóveda: clave) def self.detectar_clave_boveda(contenido) if contenido =~ /\*\*SSH\*\*:.*Bóveda:\s*`?([a-zA-Z0-9_\-:]+)`?\)?/i return $1 end # Fallback: buscar en cualquier línea de credenciales if contenido =~ /[Bb]óveda:\s*`?([a-zA-Z0-9_\-:]+)`?\)?/ return $1 end nil end # Detecta tipo de autenticación SSH # Formato: (Passphrase RSA, ...) o (Password, ...) def self.detectar_auth_type(contenido) if contenido =~ /\*\*SSH\*\*:.*\((Passphrase|Password)/i return $1.downcase == 'passphrase' ? :passphrase : :password end :password # Default para VMs Windows end end end