- Добавлена колонка 'Тип' во все таблицы истории сборок - Для push операций отображается registry вместо платформ - Сохранение пользователя при создании push лога - Исправлена ошибка с logger в push_docker_image endpoint - Улучшено отображение истории сборок с визуальными индикаторами
227 lines
6.9 KiB
Python
227 lines
6.9 KiB
Python
"""
|
||
Сервис для работы с историей команд и тестов
|
||
Автор: Сергей Антропов
|
||
Сайт: 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()
|