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,113 @@
"""
API endpoints для управления Ansible Vault
Автор: Сергей Антропов
Сайт: https://devops.org.ru
"""
from fastapi import APIRouter, Request, HTTPException, Form
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.templating import Jinja2Templates
from pathlib import Path
from typing import List, Dict
from app.core.config import settings
router = APIRouter()
templates_path = Path(__file__).parent.parent.parent.parent / "templates"
templates = Jinja2Templates(directory=str(templates_path))
@router.get("/vault", response_class=HTMLResponse)
async def vault_page(request: Request):
"""Страница управления Ansible Vault"""
vault_dir = settings.PROJECT_ROOT / "vault"
vault_files = []
if vault_dir.exists():
# Ищем все .yml и .yaml файлы
for pattern in ["*.yml", "*.yaml"]:
for vault_file in vault_dir.glob(pattern):
if vault_file.is_file():
try:
vault_files.append({
"name": vault_file.name,
"path": str(vault_file.relative_to(settings.PROJECT_ROOT)),
"size": vault_file.stat().st_size
})
except Exception:
pass
return templates.TemplateResponse(
"pages/vault/index.html",
{
"request": request,
"vault_files": vault_files,
"vault_dir": str(vault_dir.relative_to(settings.PROJECT_ROOT)) if vault_dir.exists() else None
}
)
@router.get("/api/v1/vault/files")
async def get_vault_files():
"""API endpoint для получения списка Vault файлов"""
vault_dir = settings.PROJECT_ROOT / "vault"
vault_files = []
if vault_dir.exists():
for vault_file in vault_dir.glob("*.yml"):
vault_files.append({
"name": vault_file.name,
"path": str(vault_file),
"size": vault_file.stat().st_size
})
return {"files": vault_files}
@router.post("/api/v1/vault/encrypt")
async def encrypt_string(request: Request):
"""API endpoint для шифрования строки через Vault"""
from fastapi import Body
from app.services.vault_service import VaultService
data = await request.json()
content = data.get("content", "")
if not content:
from fastapi import HTTPException
raise HTTPException(status_code=400, detail="Содержимое не указано")
try:
vault_service = VaultService()
result = vault_service.encrypt_string(content)
return result
except ValueError as e:
from fastapi import HTTPException
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
from fastapi import HTTPException
raise HTTPException(status_code=500, detail=f"Ошибка шифрования: {str(e)}")
@router.post("/api/v1/vault/decrypt")
async def decrypt_string(request: Request):
"""API endpoint для расшифровки строки из Vault"""
from fastapi import Body
from app.services.vault_service import VaultService
data = await request.json()
content = data.get("content", "")
if not content:
from fastapi import HTTPException
raise HTTPException(status_code=400, detail="Содержимое не указано")
try:
vault_service = VaultService()
result = vault_service.decrypt_string(content)
return result
except ValueError as e:
from fastapi import HTTPException
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
from fastapi import HTTPException
raise HTTPException(status_code=500, detail=f"Ошибка расшифровки: {str(e)}")