feat: implement template-based documentation generation system for Proxmox
Some checks failed
CI/CD Pipeline / Run Tests (push) Has been cancelled
CI/CD Pipeline / Security Scanning (push) Has been cancelled
CI/CD Pipeline / Build and Push Docker Images (api) (push) Has been cancelled
CI/CD Pipeline / Build and Push Docker Images (chat) (push) Has been cancelled
CI/CD Pipeline / Build and Push Docker Images (frontend) (push) Has been cancelled
CI/CD Pipeline / Build and Push Docker Images (worker) (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Generate Documentation (push) Has started running
CI/CD Pipeline / Lint Code (push) Has started running
Some checks failed
CI/CD Pipeline / Run Tests (push) Has been cancelled
CI/CD Pipeline / Security Scanning (push) Has been cancelled
CI/CD Pipeline / Build and Push Docker Images (api) (push) Has been cancelled
CI/CD Pipeline / Build and Push Docker Images (chat) (push) Has been cancelled
CI/CD Pipeline / Build and Push Docker Images (frontend) (push) Has been cancelled
CI/CD Pipeline / Build and Push Docker Images (worker) (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Generate Documentation (push) Has started running
CI/CD Pipeline / Lint Code (push) Has started running
Implement a scalable system for automatic documentation generation from infrastructure systems, preventing LLM context overload through template-driven sectioning. **New Features:** 1. **YAML Template System** (`templates/documentation/proxmox.yaml`) - Define documentation sections independently - Specify data requirements per section - Configure prompts, generation settings, and scheduling - Prevents LLM context overflow by sectioning data 2. **Template-Based Generator** (`src/datacenter_docs/generators/template_generator.py`) - Load and parse YAML templates - Generate documentation sections independently - Extract only required data for each section - Save sections individually to files and database - Combine sections with table of contents 3. **Celery Tasks** (`src/datacenter_docs/workers/documentation_tasks.py`) - `collect_and_generate_docs`: Collect data and generate docs - `generate_proxmox_docs`: Scheduled Proxmox documentation (daily at 2 AM) - `generate_all_docs`: Generate docs for all systems in parallel - `index_generated_docs`: Index generated docs into vector store for RAG - `full_docs_pipeline`: Complete workflow (collect → generate → index) 4. **Scheduled Jobs** (updated `celery_app.py`) - Daily Proxmox documentation generation - Every 6 hours: all systems documentation - Weekly: full pipeline with indexing - Proper task routing and rate limiting 5. **Test Script** (`scripts/test_proxmox_docs.py`) - End-to-end testing of documentation generation - Mock data collection from Proxmox - Template-based generation - File and database storage 6. **Configuration Updates** (`src/datacenter_docs/utils/config.py`) - Add port configuration fields for Docker services - Add MongoDB and Redis credentials - Support all required environment variables **Proxmox Documentation Sections:** - Infrastructure Overview (cluster, nodes, stats) - Virtual Machines Inventory - LXC Containers Inventory - Storage Configuration - Network Configuration - Maintenance Procedures **Benefits:** - Scalable to multiple infrastructure systems - Prevents LLM context window overflow - Independent section generation - Scheduled automatic updates - Vector store integration for RAG chat - Template-driven approach for consistency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
162
scripts/test_proxmox_docs.py
Executable file
162
scripts/test_proxmox_docs.py
Executable file
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script for Proxmox documentation generation
|
||||
|
||||
Tests the end-to-end workflow:
|
||||
1. Collect data from Proxmox (using mock data)
|
||||
2. Generate documentation using template
|
||||
3. Save sections to files and database
|
||||
4. Optionally index for RAG
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add src to path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
|
||||
|
||||
from datacenter_docs.collectors.proxmox_collector import ProxmoxCollector
|
||||
from datacenter_docs.generators.template_generator import TemplateBasedGenerator
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def test_proxmox_documentation() -> None:
|
||||
"""Test complete Proxmox documentation generation workflow"""
|
||||
|
||||
logger.info("=" * 80)
|
||||
logger.info("PROXMOX DOCUMENTATION GENERATION TEST")
|
||||
logger.info("=" * 80)
|
||||
|
||||
# Step 1: Collect data from Proxmox
|
||||
logger.info("\n📊 STEP 1: Collecting data from Proxmox...")
|
||||
logger.info("-" * 80)
|
||||
|
||||
collector = ProxmoxCollector()
|
||||
collect_result = await collector.run()
|
||||
|
||||
if not collect_result["success"]:
|
||||
logger.error(f"❌ Data collection failed: {collect_result.get('error')}")
|
||||
return
|
||||
|
||||
logger.info("✅ Data collection successful!")
|
||||
logger.info(f" Collected at: {collect_result['data']['metadata']['collected_at']}")
|
||||
|
||||
# Show statistics
|
||||
stats = collect_result["data"]["data"].get("statistics", {})
|
||||
logger.info("\n📈 Infrastructure Statistics:")
|
||||
logger.info(f" Total VMs: {stats.get('total_vms', 0)}")
|
||||
logger.info(f" Running VMs: {stats.get('running_vms', 0)}")
|
||||
logger.info(f" Total Containers: {stats.get('total_containers', 0)}")
|
||||
logger.info(f" Running Containers: {stats.get('running_containers', 0)}")
|
||||
logger.info(f" Total Nodes: {stats.get('total_nodes', 0)}")
|
||||
logger.info(f" Total CPU Cores: {stats.get('total_cpu_cores', 0)}")
|
||||
logger.info(f" Total Memory: {stats.get('total_memory_gb', 0)} GB")
|
||||
logger.info(f" Total Storage: {stats.get('total_storage_tb', 0)} TB")
|
||||
|
||||
# Step 2: Generate documentation using template
|
||||
logger.info("\n📝 STEP 2: Generating documentation using template...")
|
||||
logger.info("-" * 80)
|
||||
|
||||
template_path = "templates/documentation/proxmox.yaml"
|
||||
|
||||
try:
|
||||
generator = TemplateBasedGenerator(template_path)
|
||||
except FileNotFoundError:
|
||||
logger.error(f"❌ Template not found: {template_path}")
|
||||
logger.info(" Creating template directory and file...")
|
||||
|
||||
# Create template directory
|
||||
template_dir = Path(template_path).parent
|
||||
template_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
logger.error(
|
||||
" Please ensure the template file exists at: "
|
||||
f"{Path(template_path).absolute()}"
|
||||
)
|
||||
return
|
||||
|
||||
logger.info(f"✅ Template loaded: {generator.template.name}")
|
||||
logger.info(f" Sections to generate: {len(generator.template.sections)}")
|
||||
|
||||
# List all sections
|
||||
for i, section in enumerate(generator.template.sections, 1):
|
||||
logger.info(f" {i}. {section.get('title')} (ID: {section.get('id')})")
|
||||
|
||||
# Step 3: Generate and save all sections
|
||||
logger.info("\n🔨 STEP 3: Generating documentation sections...")
|
||||
logger.info("-" * 80)
|
||||
|
||||
sections_results = await generator.generate_and_save_sections(
|
||||
data=collect_result["data"], save_individually=True
|
||||
)
|
||||
|
||||
# Show results
|
||||
sections_generated = sum(1 for r in sections_results if r.get("success"))
|
||||
sections_failed = sum(1 for r in sections_results if not r.get("success"))
|
||||
|
||||
logger.info(f"\n✅ Generation completed!")
|
||||
logger.info(f" Sections generated: {sections_generated}")
|
||||
logger.info(f" Sections failed: {sections_failed}")
|
||||
|
||||
# Show each section result
|
||||
logger.info("\n📋 Section Results:")
|
||||
for result in sections_results:
|
||||
if result.get("success"):
|
||||
logger.info(f" ✅ {result.get('title')}")
|
||||
if "file_path" in result:
|
||||
logger.info(f" File: {result.get('file_path')}")
|
||||
else:
|
||||
logger.info(f" ❌ {result.get('section_id')}: {result.get('error')}")
|
||||
|
||||
# Step 4: Summary
|
||||
logger.info("\n" + "=" * 80)
|
||||
logger.info("SUMMARY")
|
||||
logger.info("=" * 80)
|
||||
logger.info(f"✅ Data Collection: SUCCESS")
|
||||
logger.info(
|
||||
f"✅ Documentation Generation: {sections_generated}/{len(sections_results)} sections"
|
||||
)
|
||||
|
||||
if sections_failed == 0:
|
||||
logger.info("\n🎉 All tests passed successfully!")
|
||||
else:
|
||||
logger.warning(f"\n⚠️ {sections_failed} section(s) failed to generate")
|
||||
|
||||
# Show output directory
|
||||
output_dir = Path(generator.template.output_config.get("directory", "output"))
|
||||
if output_dir.exists():
|
||||
logger.info(f"\n📁 Generated files available in: {output_dir.absolute()}")
|
||||
md_files = list(output_dir.glob("**/*.md"))
|
||||
if md_files:
|
||||
logger.info(f" Total markdown files: {len(md_files)}")
|
||||
for md_file in md_files[:10]: # Show first 10
|
||||
logger.info(f" - {md_file.relative_to(output_dir)}")
|
||||
if len(md_files) > 10:
|
||||
logger.info(f" ... and {len(md_files) - 10} more")
|
||||
|
||||
logger.info("\n" + "=" * 80)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""Main entry point"""
|
||||
try:
|
||||
asyncio.run(test_proxmox_documentation())
|
||||
except KeyboardInterrupt:
|
||||
logger.info("\n\n⚠️ Test interrupted by user")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
logger.error(f"\n\n❌ Test failed with error: {e}", exc_info=True)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user