# frozen_string_literal: true require 'optparse' require_relative '../core/colores' class SubcomandoContexto def initialize(args, logger) @args = args @logger = logger @opciones = { cmd: false } end def ejecutar if @args.empty? @logger.error("Se requiere nombre de nodo") puts "Uso: ./adn/tools/run contexto [--cmd]" exit 1 end nodo = @args[0] @args.shift parser = OptionParser.new do |opts| opts.banner = "Uso: ./adn/tools/run contexto [OPCIONES]" opts.separator "" opts.separator "Obtiene contexto topológico de un nodo" opts.separator "" opts.separator "Opciones:" opts.on("--cmd", "Generar comando SSH con ProxyJump si es necesario") do @opciones[:cmd] = true end opts.on("-h", "--help", "Mostrar esta ayuda") do puts opts exit end end begin parser.parse!(@args) rescue OptionParser::InvalidOption => e @logger.error("Opción inválida: #{e.message}") puts parser exit 1 end obtener_contexto(nodo) end private def obtener_contexto(nombre_nodo) @logger.info("Buscando contexto para nodo: #{nombre_nodo}") ruta_nodo = File.join(ADN::NODOS_DIR, "#{nombre_nodo}.md") unless File.exist?(ruta_nodo) @logger.error("Nodo no encontrado: #{nombre_nodo}") puts "#{Color::RED}✗ No se encontró ficha para el nodo '#{nombre_nodo}'#{Color::RESET}" puts " Buscado en: #{ruta_nodo}" exit 1 end contenido = File.read(ruta_nodo, encoding: 'UTF-8') # Extraer información básica puts "#{Color::CYAN}📋 Contexto del nodo: #{nombre_nodo}#{Color::RESET}" puts "#{Color::DIM}#{'-' * 60}#{Color::RESET}" # Buscar IP en la tabla if contenido.match(/\|\s*IP (?:LAN|Pública)?\s*\|\s*([^\|]+)\s*\|/) ip = $1.strip puts " #{Color::GREEN}IP:#{Color::RESET} #{ip}" if @opciones[:cmd] generar_comando_ssh(nombre_nodo, ip) end end # Buscar rol if contenido.match(/\|\s*Rol(?: Principal)?\s*\|\s*([^\|]+)\s*\|/) rol = $1.strip puts " #{Color::GREEN}Rol:#{Color::RESET} #{rol}" end # Buscar sistema operativo if contenido.match(/\|\s*Sistema Operativo\s*\|\s*([^\|]+)\s*\|/) so = $1.strip puts " #{Color::GREEN}SO:#{Color::RESET} #{so}" end # Buscar en ontología para contexto de red config_path = File.join(__dir__, '../config', 'config.yml') ontologia_path = File.join(ADN::PROJECT_ROOT, 'adn', '01_ontologia.md') if File.exist?(ontologia_path) ontologia = File.read(ontologia_path, encoding: 'UTF-8') if ontologia.include?(nombre_nodo) puts " #{Color::GREEN}En ontología:#{Color::RESET} Sí" # Intentar encontrar en qué cluster está clusters = ['srv-pmox1', 'srv-pmox2', 'srv-pmox3', 'srv-xen1', 'srv-dasu'] cluster = clusters.find { |c| ontologia.include?("**#{c}**") && ontologia.include?(nombre_nodo) } if cluster puts " #{Color::GREEN}Cluster:#{Color::RESET} #{cluster}" # Determinar si necesita ProxyJump if cluster != 'srv-ns8' && !nombre_nodo.start_with?('srv-') puts " #{Color::YELLOW}🔧 Acceso probable via ProxyJump:#{Color::RESET}" puts " ssh -J root@#{cluster} rmonla@#{nombre_nodo}" end end end end puts "#{Color::DIM}#{'-' * 60}#{Color::RESET}" @logger.exito("Contexto obtenido para nodo: #{nombre_nodo}") end def generar_comando_ssh(nodo, ip) puts "\n#{Color::CYAN}🔧 Comando SSH sugerido:#{Color::RESET}" # Determinar usuario basado en el nodo usuario = if nodo.start_with?('srvv-') || nodo.start_with?('pcv-') 'rmonla' elsif nodo.start_with?('srv-') && nodo != 'srv-ns8' 'root' else 'rmonla' end puts " ssh #{usuario}@#{ip}" # Si no es srv-ns8 y no es un hypervisor, sugerir usando nombre unless nodo == 'srv-ns8' || nodo.start_with?('srv-pmox') || nodo.start_with?('srv-xen') puts " #{Color::DIM}O usando nombre (si está en ~/.ssh/config):#{Color::RESET}" puts " ssh #{nodo}" end end end