Arquitectura antes: core/nodos_info.rb → usado por 4 CLIs core/ejecutor_remoto.rb → usado por proceso.rb core/triggers.rb → usado por triggers.rb core/eventos.rb → usado por triggers.rb core/configurador.rb → usado por backup.rb Arquitectura después: cli/nodos/info.rb ← submódulo de nodos cli/ssh/ejecutor.rb ← submódulo de ssh cli/triggers/motor.rb ← submódulo de triggers cli/triggers/eventos.rb ← submódulo de triggers cli/backup/configurador.rb ← submódulo de backup core/ queda limpio con solo infraestructura genuina: colores, constants, error_handler, logger, help_formatter, conciliador (transversal), validador (obsoleto) - 15 tests pasan sin regresiones - Evento 1078 (17:14→17:17)
135 lines
4.1 KiB
Ruby
135 lines
4.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# adn/tools/cli/nodos/info.rb — Utilidades para extracción de metadatos de fichas de nodos
|
|
# ======================================================================================
|
|
|
|
require_relative '../../core/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
|