Files
DevOpsLab/app/api/v1/endpoints/docker.py
Сергей Антропов 1fbf9185a2 feat: добавлена пометка типа операции (Build/Push) в истории сборок Dockerfile
- Добавлена колонка 'Тип' во все таблицы истории сборок
- Для push операций отображается registry вместо платформ
- Сохранение пользователя при создании push лога
- Исправлена ошибка с logger в push_docker_image endpoint
- Улучшено отображение истории сборок с визуальными индикаторами
2026-02-15 22:59:02 +03:00

117 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
API endpoints для управления Docker образами
Автор: Сергей Антропов
Сайт: https://devops.org.ru
"""
from fastapi import APIRouter, Request, HTTPException
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
from app.core.docker_client import DockerClient
router = APIRouter()
templates_path = Path(__file__).parent.parent.parent.parent / "templates"
templates = Jinja2Templates(directory=str(templates_path))
def get_docker_client():
"""Получение Docker клиента с обработкой ошибок"""
try:
return DockerClient()
except Exception:
return None
@router.get("/docker", response_class=HTMLResponse)
async def docker_page(request: Request):
"""Страница управления Docker образами"""
docker_client = get_docker_client()
images = []
if docker_client:
try:
images = docker_client.list_images()
except Exception:
pass
return templates.TemplateResponse(
"pages/docker/index.html",
{
"request": request,
"images": images
}
)
@router.get("/api/v1/docker/images", response_class=HTMLResponse)
async def get_docker_images():
"""API endpoint для получения списка Docker образов"""
docker_client = get_docker_client()
if not docker_client:
return """
<div class="alert alert-warning">
<i class="fas fa-exclamation-triangle me-2"></i>
<strong>Docker недоступен</strong>
<br><small class="text-muted">Убедитесь, что Docker запущен и доступен. Проверьте, что Docker socket доступен: <code>/var/run/docker.sock</code></small>
</div>
"""
try:
images = docker_client.list_images()
if not images:
return """
<div class="text-center py-5">
<i class="fab fa-docker fa-3x text-muted mb-3"></i>
<p class="text-muted">Docker образы не найдены</p>
</div>
"""
html = '<div class="table-responsive"><table class="table table-hover"><thead><tr><th>ID</th><th>Теги</th><th>Размер</th><th>Создан</th></tr></thead><tbody>'
for img in images:
size_mb = (img.get("size", 0) / 1024 / 1024) if img.get("size") else 0
size_str = f"{size_mb:.2f} MB" if size_mb > 0 else "N/A"
tags_list = img.get("tags", [])
if tags_list:
tags = " ".join([f'<span class="badge bg-info me-1">{tag}</span>' for tag in tags_list])
else:
tags = '<span class="text-muted">нет тегов</span>'
img_id = img.get("id", "")[:12] if img.get("id") else "N/A"
created = img.get("created", "")
if created:
try:
# Парсим ISO формат даты или timestamp
from datetime import datetime
if isinstance(created, (int, float)):
# Unix timestamp
dt = datetime.fromtimestamp(created)
created_str = dt.strftime('%d.%m.%Y %H:%M')
elif isinstance(created, str):
# ISO формат
try:
dt = datetime.fromisoformat(created.replace('Z', '+00:00'))
except:
# Пробуем другой формат
dt = datetime.strptime(created.split('.')[0], '%Y-%m-%dT%H:%M:%S')
created_str = dt.strftime('%d.%m.%Y %H:%M')
else:
created_str = str(created)
except Exception as e:
created_str = str(created)
else:
created_str = "N/A"
html += f'<tr><td><code>{img_id}</code></td><td>{tags}</td><td>{size_str}</td><td>{created_str}</td></tr>'
html += '</tbody></table></div>'
return html
except Exception as e:
return f"""
<div class="alert alert-danger">
<i class="fas fa-exclamation-circle me-2"></i>
<strong>Ошибка при получении списка образов:</strong> {str(e)}
</div>
"""