feat: добавлена пометка типа операции (Build/Push) в истории сборок Dockerfile

- Добавлена колонка 'Тип' во все таблицы истории сборок
- Для push операций отображается registry вместо платформ
- Сохранение пользователя при создании push лога
- Исправлена ошибка с logger в push_docker_image endpoint
- Улучшено отображение истории сборок с визуальными индикаторами
This commit is contained in:
Сергей Антропов
2026-02-15 22:59:02 +03:00
parent 23e1a6037b
commit 1fbf9185a2
232 changed files with 38075 additions and 5 deletions

View File

@@ -0,0 +1,133 @@
"""
Сервис для развертывания ролей на реальные серверы
Автор: Сергей Антропов
Сайт: https://devops.org.ru
"""
import asyncio
from pathlib import Path
from typing import Optional, AsyncGenerator, Dict, List
from datetime import datetime
from app.core.config import settings
from app.core.ansible_executor import AnsibleExecutor
class DeploymentService:
"""Развертывание ролей на реальные серверы"""
def __init__(self):
self.project_root = settings.PROJECT_ROOT
self.inventory_file = self.project_root / "inventory" / "hosts.ini"
self.deploy_playbook = self.project_root / "roles" / "deploy.yml"
self.ansible_executor = AnsibleExecutor()
async def deploy_role(
self,
role_name: str,
inventory: Optional[str] = None,
limit: Optional[str] = None,
tags: Optional[List[str]] = None,
check: bool = False,
extra_vars: Optional[Dict] = None,
stream: bool = False
) -> AsyncGenerator[str, None]:
"""
Развертывание роли на реальные серверы
Args:
role_name: Имя роли для развертывания
inventory: Путь к inventory файлу (по умолчанию inventory/hosts.ini)
limit: Ограничение на хосты
tags: Список тегов для фильтрации
check: Режим dry-run (--check)
extra_vars: Дополнительные переменные
stream: Если True, возвращает генератор строк
Yields:
Строки вывода команды
"""
# Проверка существования роли
role_path = self.project_root / "roles" / role_name
if not role_path.exists():
yield f"❌ Роль '{role_name}' не найдена\n"
return
# Определение inventory файла
if inventory:
inventory_path = Path(inventory)
if not inventory_path.is_absolute():
inventory_path = self.project_root / inventory_path
else:
inventory_path = self.inventory_file
if not inventory_path.exists():
yield f"❌ Inventory файл '{inventory_path}' не найден\n"
yield "💡 Создайте файл inventory/hosts.ini с вашими серверами\n"
return
# Проверка deploy.yml
if not self.deploy_playbook.exists():
yield f"❌ Playbook '{self.deploy_playbook}' не найден\n"
return
# Формирование тегов
deploy_tags = [role_name]
if tags:
deploy_tags.extend(tags)
yield f"🚀 Развертывание роли '{role_name}' на реальные серверы...\n"
if check:
yield "⚠️ Режим dry-run (--check) - изменения не будут применены\n"
yield f"📋 Inventory: {inventory_path}\n"
if limit:
yield f"📋 Limit: {limit}\n"
yield f"📋 Tags: {', '.join(deploy_tags)}\n\n"
# Запуск ansible-playbook
async for line in self.ansible_executor.run_playbook(
playbook_path=str(self.deploy_playbook),
inventory=str(inventory_path),
tags=deploy_tags,
limit=limit,
check=check,
extra_vars=extra_vars,
stream=True
):
yield line
yield "\n✅ Развертывание завершено\n"
async def dry_run_role(
self,
role_name: str,
inventory: Optional[str] = None,
limit: Optional[str] = None,
stream: bool = False
) -> AsyncGenerator[str, None]:
"""
Dry-run проверка роли на реальных серверах (без изменений)
Args:
role_name: Имя роли
inventory: Путь к inventory файлу
limit: Ограничение на хосты
stream: Если True, возвращает генератор строк
Yields:
Строки вывода команды
"""
yield f"🔍 Dry-run проверка роли '{role_name}' на реальных серверах...\n"
yield "⚠️ Безопасно: не изменяет серверы, только проверяет\n\n"
async for line in self.deploy_role(
role_name=role_name,
inventory=inventory,
limit=limit,
check=True,
stream=True
):
yield line
def detect_log_level(self, line: str) -> str:
"""Определение уровня лога из строки"""
return self.ansible_executor.detect_log_level(line)