""" Сервис для работы с историей команд и тестов Автор: Сергей Антропов Сайт: https://devops.org.ru """ from datetime import datetime from typing import Dict, List, Optional from sqlalchemy.orm import Session from app.models.database import ( CommandHistory, TestResult, DeploymentHistory, ExportHistory, ImportHistory ) from app.db.session import get_db class HistoryService: """Сервис для работы с историей""" def save_command( self, command: str, command_type: str, role_name: Optional[str] = None, preset_name: Optional[str] = None, status: str = "running", user: Optional[str] = None ) -> int: """Сохранение команды в историю""" db = next(get_db()) try: cmd_history = CommandHistory( command=command, command_type=command_type, role_name=role_name, preset_name=preset_name, status=status, user=user, started_at=datetime.utcnow() ) db.add(cmd_history) db.commit() db.refresh(cmd_history) return cmd_history.id finally: db.close() def update_command( self, command_id: int, status: str, stdout: Optional[str] = None, stderr: Optional[str] = None, returncode: Optional[int] = None ): """Обновление команды после выполнения""" db = next(get_db()) try: cmd = db.query(CommandHistory).filter(CommandHistory.id == command_id).first() if cmd: cmd.status = status cmd.stdout = stdout cmd.stderr = stderr cmd.returncode = returncode cmd.finished_at = datetime.utcnow() if cmd.started_at: duration = (cmd.finished_at - cmd.started_at).total_seconds() cmd.duration = int(duration) db.commit() finally: db.close() def get_command_history( self, limit: int = 50, role_name: Optional[str] = None, command_type: Optional[str] = None ) -> List[Dict]: """Получение истории команд""" db = next(get_db()) try: query = db.query(CommandHistory) if role_name: query = query.filter(CommandHistory.role_name == role_name) if command_type: query = query.filter(CommandHistory.command_type == command_type) commands = query.order_by(CommandHistory.started_at.desc()).limit(limit).all() return [ { "id": cmd.id, "command": cmd.command, "command_type": cmd.command_type, "role_name": cmd.role_name, "preset_name": cmd.preset_name, "status": cmd.status, "started_at": cmd.started_at.isoformat() if cmd.started_at else None, "finished_at": cmd.finished_at.isoformat() if cmd.finished_at else None, "duration": cmd.duration } for cmd in commands ] finally: db.close() def save_test_result( self, command_id: int, role_name: str, preset_name: Optional[str], test_type: str, status: str, output: Optional[str] = None, error: Optional[str] = None, duration: Optional[int] = None ) -> int: """Сохранение результата теста""" db = next(get_db()) try: test_result = TestResult( command_id=command_id, role_name=role_name, preset_name=preset_name, test_type=test_type, status=status, output=output, error=error, duration=duration, created_at=datetime.utcnow() ) db.add(test_result) db.commit() db.refresh(test_result) return test_result.id finally: db.close() def save_deployment( self, role_name: str, inventory: str, hosts: List[str], status: str, output: Optional[str] = None, error: Optional[str] = None, user: Optional[str] = None ) -> int: """Сохранение истории деплоя""" db = next(get_db()) try: deployment = DeploymentHistory( role_name=role_name, inventory=inventory, hosts=hosts, status=status, output=output, error=error, user=user, started_at=datetime.utcnow() ) db.add(deployment) db.commit() db.refresh(deployment) return deployment.id finally: db.close() def save_export( self, role_name: str, repo_url: str, branch: str, version: Optional[str], commit_hash: Optional[str], status: str, user: Optional[str] = None ) -> int: """Сохранение истории экспорта""" db = next(get_db()) try: export = ExportHistory( role_name=role_name, repo_url=repo_url, branch=branch, version=version, commit_hash=commit_hash, status=status, user=user, started_at=datetime.utcnow(), finished_at=datetime.utcnow() if status != "running" else None ) db.add(export) db.commit() db.refresh(export) return export.id finally: db.close() def save_import( self, role_name: str, source_type: str, source_url: Optional[str], status: str, user: Optional[str] = None ) -> int: """Сохранение истории импорта""" db = next(get_db()) try: import_history = ImportHistory( role_name=role_name, source_type=source_type, source_url=source_url, status=status, user=user, started_at=datetime.utcnow(), finished_at=datetime.utcnow() if status != "running" else None ) db.add(import_history) db.commit() db.refresh(import_history) return import_history.id finally: db.close()