# 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/hito' require_relative 'db/misc' include SubcomandoDBBitacora include SubcomandoDBEvento include SubcomandoDBNodo include SubcomandoDBHito include SubcomandoDBMisc # Inicializa el subcomando con argumentos y logger # # @param args [Array] 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 '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 'backup' comando_backup(sub_args) when 'archivar:md' comando_archivar_md 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 end # Muestra la ayuda general del subcomando def mostrar_ayuda ayuda = ADN::HelpFormatter.generar_help( titulo: "Operaciones de Base de Datos ADN", descripcion: "Integra las operaciones de base de datos PostgreSQL con la CLI ADN", uso: "./adn/tools/run db [SUBCOMANDO] [OPCIONES]", opciones: [ { names: ['salud:bd'], desc: "Verificar conexión y estado de la BD" }, { names: ['backup [OPCIONES]'], desc: "Crear backup de la base de datos" }, { names: ['bitacora:crear [FECHA]'], desc: "Crear nueva bitácora diaria" }, { names: ['bitacora:listar [OPCIONES]'], desc: "Listar bitácoras existentes" }, { names: ['evento:crear [OPCIONES]'], desc: "Crear nueva entrada cronológica" }, { names: ['evento:listar [OPCIONES]'], desc: "Listar entradas con filtros" }, { names: ['nodo:crear [OPCIONES]'], desc: "Crear nuevo nodo (servidor/VM/PC)" }, { names: ['nodo:listar [OPCIONES]'], desc: "Listar nodos del sistema" }, { names: ['estadisticas'], desc: "Mostrar estadísticas del sistema" }, { names: ['archivar:md'], desc: "Mueve los archivos .md migrados al archivo histórico" } ], ejemplos: [ { cmd: "./adn/tools/run db salud:bd", desc: "Verificar conexión y estado de la BD" }, { cmd: "./adn/tools/run db bitacora:crear --resumen \"Inicio de proyecto\"", desc: "Crear bitácora con resumen" }, { cmd: "./adn/tools/run db evento:crear --inicio 09:00 --descripcion \"Reunión\" --nodo srv-ns8", desc: "Crear entrada de evento" }, { cmd: "./adn/tools/run db nodo:listar --tipo servidor", desc: "Listar nodos de tipo servidor" } ] ) puts ayuda puts "" puts "#{Color::YELLOW}⚠ Nota:#{Color::RESET} Requiere PostgreSQL en ejecución (puerto 5433)" puts " Iniciar contenedor: #{Color::DIM}cd dtic-BITACORAs && docker-compose up -d#{Color::RESET}" end end end module ADN class SubcomandoDB require_relative 'db/bitacora' require_relative 'db/evento' require_relative 'db/nodo' require_relative 'db/hito' require_relative 'db/misc' include SubcomandoDBBitacora include SubcomandoDBEvento include SubcomandoDBNodo include SubcomandoDBHito include SubcomandoDBMisc # Inicializa el subcomando con argumentos y logger # # @param args [Array] 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 '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 'backup' comando_backup(sub_args) when 'archivar:md' comando_archivar_md 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 end # Muestra la ayuda general del subcomando def mostrar_ayuda puts "#{Color::BOLD}Uso: ./adn/tools/run db [SUBCOMANDO] [OPCIONES]#{Color::RESET}" puts "" puts "#{Color::BOLD}Subcomandos disponibles:#{Color::RESET}" puts "" puts " #{Color::CYAN}salud:bd#{Color::RESET} Verificar conexión y estado de la BD" puts " #{Color::CYAN}backup [OPCIONES]#{Color::RESET} Crear backup de la base de datos" puts " #{Color::CYAN}bitacora:crear [FECHA]#{Color::RESET} Crear nueva bitácora diaria" puts " #{Color::CYAN}bitacora:listar [OPCIONES]#{Color::RESET} Listar bitácoras existentes" puts " #{Color::CYAN}evento:crear [OPCIONES]#{Color::RESET} Crear nueva entrada cronológica" puts " #{Color::CYAN}evento:listar [OPCIONES]#{Color::RESET} Listar entradas con filtros" puts " #{Color::CYAN}nodo:crear [OPCIONES]#{Color::RESET} Crear nuevo nodo (servidor/VM/PC)" puts " #{Color::CYAN}nodo:listar [OPCIONES]#{Color::RESET} Listar nodos del sistema" puts " #{Color::CYAN}estadisticas#{Color::RESET} Mostrar estadísticas del sistema" puts " #{Color::CYAN}archivar:md#{Color::RESET} Mueve los archivos .md migrados al archivo histórico" puts "" puts "#{Color::BOLD}Ejemplos:#{Color::RESET}" puts " ./adn/tools/run db salud:bd" puts " ./adn/tools/run db bitacora:crear --resumen \"Inicio de proyecto\"" puts " ./adn/tools/run db evento:crear --inicio 09:00 --descripcion \"Reunión\" --nodo srv-ns8" puts " ./adn/tools/run db nodo:listar --tipo servidor" puts "" puts "#{Color::YELLOW}⚠ Nota:#{Color::RESET} Requiere PostgreSQL en ejecución (puerto 5433)" puts " Iniciar contenedor: #{Color::DIM}cd dtic-BITACORAs && docker-compose up -d#{Color::RESET}" end end end