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

262 lines
11 KiB
Python
Raw Permalink 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.

"""
Модели базы данных для истории команд и тестов
Автор: Сергей Антропов
Сайт: https://devops.org.ru
"""
from sqlalchemy import Column, Integer, String, DateTime, Text, Boolean, JSON, ForeignKey
from sqlalchemy.orm import relationship
from datetime import datetime
# Импортируем Base из user.py для единообразия
from app.models.user import Base
class CommandHistory(Base):
"""История выполнения команд"""
__tablename__ = "command_history"
id = Column(Integer, primary_key=True, index=True)
command = Column(String, nullable=False, index=True)
command_type = Column(String, nullable=False, index=True) # test, deploy, export, import
role_name = Column(String, index=True)
preset_name = Column(String)
status = Column(String, nullable=False) # success, failed, running
stdout = Column(Text)
stderr = Column(Text)
returncode = Column(Integer)
started_at = Column(DateTime, default=datetime.utcnow, nullable=False)
finished_at = Column(DateTime)
duration = Column(Integer) # в секундах
user = Column(String)
extra_data = Column(JSON) # Дополнительные данные
# Связи
test_results = relationship("TestResult", back_populates="command")
class TestResult(Base):
"""Результаты тестирования ролей"""
__tablename__ = "test_results"
id = Column(Integer, primary_key=True, index=True)
command_id = Column(Integer, ForeignKey("command_history.id"), nullable=False)
role_name = Column(String, nullable=False, index=True)
preset_name = Column(String, index=True)
test_type = Column(String) # molecule, lint, syntax
status = Column(String, nullable=False) # passed, failed, skipped
duration = Column(Integer) # в секундах
output = Column(Text)
error = Column(Text)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
# Связи
command = relationship("CommandHistory", back_populates="test_results")
class DeploymentHistory(Base):
"""История деплоев"""
__tablename__ = "deployment_history"
id = Column(Integer, primary_key=True, index=True)
role_name = Column(String, nullable=False, index=True)
inventory = Column(String)
hosts = Column(JSON) # Список хостов
status = Column(String, nullable=False) # success, failed, running
started_at = Column(DateTime, default=datetime.utcnow, nullable=False)
finished_at = Column(DateTime)
duration = Column(Integer)
output = Column(Text)
error = Column(Text)
user = Column(String)
extra_data = Column(JSON)
class ExportHistory(Base):
"""История экспорта ролей"""
__tablename__ = "export_history"
id = Column(Integer, primary_key=True, index=True)
role_name = Column(String, nullable=False, index=True)
repo_url = Column(String, nullable=False)
branch = Column(String)
version = Column(String)
commit_hash = Column(String)
status = Column(String, nullable=False) # success, failed
started_at = Column(DateTime, default=datetime.utcnow, nullable=False)
finished_at = Column(DateTime)
user = Column(String)
extra_data = Column(JSON)
class ImportHistory(Base):
"""История импорта ролей"""
__tablename__ = "import_history"
id = Column(Integer, primary_key=True, index=True)
role_name = Column(String, nullable=False, index=True)
source_type = Column(String, nullable=False) # git, galaxy
source_url = Column(String)
status = Column(String, nullable=False) # success, failed
started_at = Column(DateTime, default=datetime.utcnow, nullable=False)
finished_at = Column(DateTime)
user = Column(String)
extra_data = Column(JSON)
class Playbook(Base):
"""Playbook - объединение ролей для тестирования и деплоя"""
__tablename__ = "playbooks"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, unique=True, nullable=False, index=True)
description = Column(Text)
content = Column(Text, nullable=False) # YAML содержимое playbook
roles = Column(JSON, nullable=False) # Список ролей в playbook
variables = Column(JSON) # Переменные для playbook
inventory = Column(Text) # Инвентарь для playbook
status = Column(String, default="active") # active, archived
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
created_by = Column(String)
updated_by = Column(String)
extra_data = Column(JSON)
# Связи
test_runs = relationship("PlaybookTestRun", back_populates="playbook")
deployments = relationship("PlaybookDeployment", back_populates="playbook")
class PlaybookTestRun(Base):
"""Результаты тестирования playbook"""
__tablename__ = "playbook_test_runs"
id = Column(Integer, primary_key=True, index=True)
playbook_id = Column(Integer, ForeignKey("playbooks.id"), nullable=False)
preset_name = Column(String, index=True)
status = Column(String, nullable=False) # running, success, failed, cancelled
started_at = Column(DateTime, default=datetime.utcnow, nullable=False)
finished_at = Column(DateTime)
duration = Column(Integer) # в секундах
output = Column(Text)
error = Column(Text)
returncode = Column(Integer)
user = Column(String)
extra_data = Column(JSON)
# Связи
playbook = relationship("Playbook", back_populates="test_runs")
class PlaybookDeployment(Base):
"""Результаты деплоя playbook"""
__tablename__ = "playbook_deployments"
id = Column(Integer, primary_key=True, index=True)
playbook_id = Column(Integer, ForeignKey("playbooks.id"), nullable=False)
inventory = Column(Text)
hosts = Column(JSON) # Список хостов
status = Column(String, nullable=False) # running, success, failed, cancelled
started_at = Column(DateTime, default=datetime.utcnow, nullable=False)
finished_at = Column(DateTime)
duration = Column(Integer) # в секундах
output = Column(Text)
error = Column(Text)
returncode = Column(Integer)
user = Column(String)
extra_data = Column(JSON)
# Связи
playbook = relationship("Playbook", back_populates="deployments")
class Dockerfile(Base):
"""Dockerfile для образов тестирования"""
__tablename__ = "dockerfiles"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, unique=True, nullable=False, index=True) # ubuntu22, centos8, etc.
description = Column(Text)
content = Column(Text, nullable=False) # Содержимое Dockerfile
base_image = Column(String) # Базовый образ
tags = Column(JSON) # Теги для образа
platforms = Column(JSON) # Платформы для сборки (по умолчанию: ["linux/amd64", "linux/386", "linux/arm64"])
status = Column(String, default="active") # active, archived
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
created_by = Column(String)
updated_by = Column(String)
extra_data = Column(JSON)
class DockerfileBuildLog(Base):
"""Логи сборки Dockerfile"""
__tablename__ = "dockerfile_build_logs"
id = Column(Integer, primary_key=True, index=True)
dockerfile_id = Column(Integer, ForeignKey("dockerfiles.id"), nullable=False, index=True)
image_name = Column(String, nullable=False, index=True)
tag = Column(String, default="latest")
platforms = Column(JSON) # Список платформ
status = Column(String, nullable=False, default="running") # running, success, failed
logs = Column(Text) # Полные логи сборки
started_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
finished_at = Column(DateTime)
duration = Column(Integer) # в секундах
returncode = Column(Integer)
user = Column(String)
extra_data = Column(JSON)
# Связи
dockerfile = relationship("Dockerfile", backref="build_logs")
class Role(Base):
"""Ansible роли"""
__tablename__ = "roles"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, unique=True, nullable=False, index=True) # Имя роли
description = Column(Text) # Описание роли
content = Column(JSON, nullable=False) # Содержимое роли в виде JSON структуры {file_path: content}
# Флаги доступа
is_global = Column(Boolean, default=False, nullable=False, index=True) # Доступно для всех пользователей
is_personal = Column(Boolean, default=False, nullable=False, index=True) # Личная роль пользователя
groups = Column(JSON) # Список групп, которым доступна роль (если is_personal=False и is_global=False)
user_id = Column(Integer, ForeignKey("users.id"), nullable=True, index=True) # Владелец роли (если is_personal=True)
# Метаданные
author = Column(String) # Автор роли
platforms = Column(JSON) # Поддерживаемые платформы
galaxy_info = Column(JSON) # Информация для Ansible Galaxy
status = Column(String, default="active") # active, archived
created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
created_by = Column(String)
updated_by = Column(String)
extra_data = Column(JSON)
# Связи
user = relationship("User", backref="roles")
class Preset(Base):
"""Preset для Molecule тестирования"""
__tablename__ = "presets"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, unique=True, nullable=False, index=True) # minimal, default, etc.
category = Column(String, default="main", index=True) # main, k8s
description = Column(Text) # Описание из комментария #description:
content = Column(Text, nullable=False) # YAML содержимое preset'а
docker_network = Column(String) # Имя Docker сети
hosts = Column(JSON) # Список хостов
images = Column(JSON) # Словарь образов
systemd_defaults = Column(JSON) # Настройки systemd
kind_clusters = Column(JSON) # Kubernetes кластеры (для k8s preset'ов)
status = Column(String, default="active") # active, archived
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
created_by = Column(String)
updated_by = Column(String)
extra_data = Column(JSON)