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)
63 lines
2.2 KiB
Ruby
63 lines
2.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# adn/tools/cli/ssh/ejecutor.rb — Abstracción para ejecución segura via SSH y Candados
|
|
# ======================================================================================
|
|
|
|
require 'open3'
|
|
require_relative '../../core/constants'
|
|
|
|
module ADN
|
|
class EjecutorRemoto
|
|
CANDADOS_CMD = ["ruby", ADN::CANDADOS_PATH]
|
|
|
|
def self.ejecutar(nodo_info, comando, options = {})
|
|
# Si es local, ejecutar directamente
|
|
if nodo_info[:ip] == 'localhost' || nodo_info[:ip] == '127.0.0.1'
|
|
puts " [LOCAL] > #{comando[0..50]}..." if options[:verbose]
|
|
output = `#{comando} 2>&1`
|
|
return { success: $?.success?, output: output }
|
|
end
|
|
|
|
clave = options[:clave] || (nodo_info[:host] == 'srv-dasu' ? 'srv-dasu:rmonla' : 'win_domain')
|
|
usuario = options[:usuario] || (nodo_info[:so] == :windows ? "monlaricardo@utnlaroja.intranet" : "rmonla")
|
|
|
|
# Construir comando SSH base como un array para evitar problemas de shell
|
|
ssh_cmd = [
|
|
"sshpass", "-e", "ssh",
|
|
"-p", (nodo_info[:puerto_ssh] || 22).to_s,
|
|
"-o", "StrictHostKeyChecking=no",
|
|
"#{usuario}@#{nodo_info[:ip]}",
|
|
comando
|
|
]
|
|
|
|
# Comando final encapsulado vía candados
|
|
# Usamos el modo array de candados: run <clave> <var> <cmd_array>
|
|
candados_full = CANDADOS_CMD + ["run", clave, "SSHPASS"] + ssh_cmd
|
|
|
|
puts " [SSH] #{nodo_info[:nombre]} (#{nodo_info[:ip]}) > #{comando[0..50]}..." if options[:verbose]
|
|
|
|
# Usar Open3 para capturar salida limpia
|
|
stdout, stderr, status = Open3.capture3(*candados_full)
|
|
|
|
{ success: status.success?, output: stdout + stderr }
|
|
end
|
|
|
|
# Pipeline para streaming (mejorado)
|
|
def self.stream_pipeline(src_array, dst_array)
|
|
begin
|
|
# Open3.pipeline acepta múltiples arrays de comando
|
|
statuses = Open3.pipeline(src_array, dst_array)
|
|
statuses.all?(&:success?)
|
|
rescue => e
|
|
puts "Error en pipeline: #{e.message}"
|
|
false
|
|
end
|
|
end
|
|
|
|
# Generador de comandos para candados (reutilizable)
|
|
def self.comando_candados(clave, env_var, comando_array)
|
|
CANDADOS_CMD + ["run", clave, env_var] + comando_array
|
|
end
|
|
end
|
|
end
|