- P2606: Plan v1.1 EN EJECUCIÓN. Fases 1-3 completadas. - Ficha nodo srvv-nginx-rm.md. P2606 en adn/07_proyectos.md. - Incluye cambios acumulados de sesiones anteriores.
199 lines
6.8 KiB
Ruby
199 lines
6.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# adn/tools/subcomando_db.rb — Subcomando para operaciones con base de datos dtic-BITACORAs
|
|
# ==============================================================================
|
|
# Este subcomando integra las operaciones de base de datos PostgreSQL con la CLI ADN.
|
|
# Proporciona comandos para gestión de bitácoras, nodos, temas y entradas directamente
|
|
# en la base de datos, permitiendo la migración gradual desde archivos .md.
|
|
#
|
|
# Comandos disponibles:
|
|
# • adn db salud:bd — Verificar conexión y estado de la BD
|
|
# • adn db bitacora:crear [FECHA] — Crear nueva bitácora diaria
|
|
# • adn db bitacora:listar [--limit N] — Listar bitácoras existentes
|
|
# • adn db evento:crear [OPCIONES] — Crear nueva entrada cronológica
|
|
# • adn db evento:listar [OPCIONES] — Listar entradas con filtros
|
|
# • adn db nodo:crear [OPCIONES] — Crear nuevo nodo (servidor/VM/PC)
|
|
# • adn db nodo:listar [OPCIONES] — Listar nodos del sistema
|
|
# • adn db migrar:md [FECHA] — Migrar bitácora .md a base de datos
|
|
# • adn db estadisticas — Mostrar estadísticas del sistema
|
|
#
|
|
# Uso:
|
|
# ./adn/tools/run db [SUBCOMANDO] [OPCIONES]
|
|
|
|
require 'optparse'
|
|
require 'date'
|
|
require 'time'
|
|
require_relative '../core/colores'
|
|
require_relative '../core/help_formatter'
|
|
|
|
# Cargar módulo BitacorasDB
|
|
begin
|
|
require_relative '../db/core/bitacora_db'
|
|
require_relative '../db/importers/md_importer'
|
|
require_relative '../db/exporters/md_exporter'
|
|
rescue LoadError => e
|
|
# Fallback para desarrollo
|
|
puts "⚠ Advertencia: No se pudo cargar BitacoraDB o MDImporter: #{e.message}"
|
|
puts " Asegúrate de que los archivos en adn/tools/db/ existen"
|
|
end
|
|
|
|
module ADN
|
|
class SubcomandoDB
|
|
require_relative 'db/bitacora'
|
|
require_relative 'db/evento'
|
|
require_relative 'db/nodo'
|
|
require_relative 'db/ambito'
|
|
require_relative 'db/hito'
|
|
require_relative 'db/misc'
|
|
include SubcomandoDBBitacora
|
|
include SubcomandoDBEvento
|
|
include SubcomandoDBAmbito
|
|
include SubcomandoDBNodo
|
|
include SubcomandoDBHito
|
|
include SubcomandoDBMisc
|
|
# Inicializa el subcomando con argumentos y logger
|
|
#
|
|
# @param args [Array<String>] Argumentos de línea de comandos
|
|
# @param logger [ADNLogger] Instancia de logger para registro
|
|
def initialize(args, logger)
|
|
@args = args
|
|
@logger = logger
|
|
@config = cargar_configuracion
|
|
end
|
|
|
|
# Ejecuta el subcomando según los argumentos proporcionados
|
|
def ejecutar
|
|
if @args.empty? || @args[0] == 'help' || @args[0] == '-h' || @args[0] == '--help'
|
|
mostrar_ayuda
|
|
return
|
|
end
|
|
|
|
subcomando = @args[0]
|
|
sub_args = @args[1..-1] || []
|
|
|
|
case subcomando
|
|
when 'salud:bd'
|
|
comando_salud_bd
|
|
when 'bitacora:crear'
|
|
comando_bitacora_crear(sub_args)
|
|
when 'bitacora:listar'
|
|
comando_bitacora_listar(sub_args)
|
|
when 'evento:crear'
|
|
comando_evento_crear(sub_args)
|
|
when 'evento:listar'
|
|
comando_evento_listar(sub_args)
|
|
when 'evento:actualizar'
|
|
comando_evento_actualizar(sub_args)
|
|
when 'evento:eliminar'
|
|
comando_evento_eliminar(sub_args)
|
|
when 'nodo:crear'
|
|
comando_nodo_crear(sub_args)
|
|
when 'nodo:listar'
|
|
comando_nodo_listar(sub_args)
|
|
when 'nodo:actualizar'
|
|
comando_nodo_actualizar(sub_args)
|
|
when 'hito:listar'
|
|
comando_hito_listar(sub_args)
|
|
when 'hito:actualizar'
|
|
comando_hito_actualizar(sub_args)
|
|
when 'hito:renombrar'
|
|
comando_hito_renombrar(sub_args)
|
|
when 'hito:ordenar'
|
|
comando_hito_ordenar(sub_args)
|
|
when 'estadisticas'
|
|
comando_estadisticas
|
|
when 'ambito:listar'
|
|
comando_ambito_listar(sub_args)
|
|
when 'ambito:crear'
|
|
comando_ambito_crear(sub_args)
|
|
when 'ambito:info'
|
|
comando_ambito_info(sub_args)
|
|
when 'ambito:nodos'
|
|
comando_ambito_nodos(sub_args)
|
|
when 'backup'
|
|
comando_backup(sub_args)
|
|
when 'archivar:md'
|
|
comando_archivar_md
|
|
when 'migrar:sql'
|
|
comando_migrar_sql(sub_args)
|
|
|
|
else
|
|
@logger.error("Subcomando desconocido: #{subcomando}")
|
|
puts "#{Color::RED}✗ Subcomando desconocido: '#{subcomando}'#{Color::RESET}"
|
|
puts ""
|
|
mostrar_ayuda
|
|
exit 1
|
|
end
|
|
rescue Interrupt
|
|
puts "\n#{Color::YELLOW}⚠ Operación interrumpida por el usuario#{Color::RESET}"
|
|
@logger.info("Operación de base de datos interrumpida por usuario")
|
|
exit 130
|
|
rescue => e
|
|
@logger.error("Error en operación de base de datos: #{e.message}", { backtrace: e.backtrace })
|
|
puts "#{Color::RED}✗ Error: #{e.message}#{Color::RESET}"
|
|
puts "#{Color::DIM}#{e.backtrace.first}#{Color::RESET}" if ENV['ADN_DEBUG']
|
|
exit 1
|
|
end
|
|
|
|
private
|
|
|
|
# ─── COMANDOS PRINCIPALES ──────────────────────────────────────────────
|
|
|
|
# ─── MÉTODOS AUXILIARES ──────────────────────────────────────────────
|
|
|
|
# Carga la configuración desde config.yml
|
|
def cargar_configuracion
|
|
config_path = File.join(__dir__, 'config.yml')
|
|
return {} unless File.exist?(config_path)
|
|
|
|
begin
|
|
YAML.load_file(config_path)
|
|
rescue => e
|
|
@logger.error("Error cargando configuración: #{e.message}")
|
|
{}
|
|
end
|
|
|
|
# Sugerir subcomandos similares basándose en distancia de Levenshtein simplificada
|
|
#
|
|
# @param subcomando [String] El subcomando ingresado por el usuario
|
|
# @return [Array<String>] Lista de subcomandos similares
|
|
def sugerir_subcomandos_similares(subcomando)
|
|
subcomandos_validos = [
|
|
'salud:bd',
|
|
'bitacora:crear',
|
|
'bitacora:listar',
|
|
'evento:crear',
|
|
'evento:listar',
|
|
'evento:actualizar',
|
|
'evento:eliminar',
|
|
'nodo:crear',
|
|
'nodo:listar',
|
|
'hito:listar',
|
|
'hito:actualizar',
|
|
'hito:renombrar',
|
|
'hito:ordenar',
|
|
'estadisticas',
|
|
'backup',
|
|
'archivar:md'
|
|
]
|
|
|
|
# Calcular distancia simple (longest common substring ratio)
|
|
similares = []
|
|
subcomandos_validos.each do |valido|
|
|
# Si empieza con las mismas letras o tiene similitud significativa
|
|
if valido.start_with?(subcomando[0, [subcomando.length, 2].min]) ||
|
|
subcomando.start_with?(valido[0, [valido.length, 2].min]) ||
|
|
(subcomando.length > 3 && valido.length > 3 &&
|
|
(valido.include?(subcomando[0,3]) || subcomando.include?(valido[0,3])))
|
|
similares << valido
|
|
end
|
|
|
|
similares.uniq
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|