- Исправлена незакрытая скобка в _build_test_command (строка 745) - Добавлена поддержка k8s preset'ов: выполнение create_k8s_cluster.py перед create.yml - Обновлены образы в k8s preset'ах: заменен недоступный ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy на inecs/ansible-lab:ubuntu22-latest - Обновлены preset'ы в базе данных через SQL - Обновлены файлы: k8s-single.yml, k8s-multi.yml, k8s-istio-full.yml
216 lines
10 KiB
Python
216 lines
10 KiB
Python
"""
|
|
Скрипт для загрузки пресетов из файловой системы в базу данных
|
|
Автор: Сергей Антропов
|
|
Сайт: https://devops.org.ru
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
from pathlib import Path
|
|
|
|
# Добавляем путь к приложению
|
|
app_path = Path(__file__).parent.parent
|
|
sys.path.insert(0, str(app_path))
|
|
# Также добавляем родительскую директорию для импорта app
|
|
if str(app_path.parent) not in sys.path:
|
|
sys.path.insert(0, str(app_path.parent))
|
|
|
|
from sqlalchemy import create_engine, text
|
|
from sqlalchemy.dialects.postgresql import JSON
|
|
import yaml
|
|
import json
|
|
from datetime import datetime
|
|
|
|
# Импортируем настройки
|
|
try:
|
|
from app.core.config import settings
|
|
except ImportError:
|
|
# Если не получается импортировать, используем значения по умолчанию
|
|
class Settings:
|
|
PROJECT_ROOT = Path("/workspace")
|
|
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://devopslab:devopslab123@postgres:5432/devopslab")
|
|
settings = Settings()
|
|
|
|
def load_presets():
|
|
"""Загрузка пресетов из файловой системы в БД"""
|
|
# Создаем подключение к БД
|
|
db_url = str(settings.DATABASE_URL).replace("postgresql+asyncpg://", "postgresql://")
|
|
engine = create_engine(db_url)
|
|
connection = engine.connect()
|
|
|
|
try:
|
|
# Получаем путь к папке presets
|
|
# Пресеты теперь находятся в alembic/presets
|
|
script_dir = Path(__file__).parent
|
|
alembic_dir = script_dir.parent / "alembic"
|
|
presets_dir = alembic_dir / "presets"
|
|
|
|
# Если не найдено в alembic, пробуем старый путь (для обратной совместимости)
|
|
if not presets_dir.exists():
|
|
project_root = Path(settings.PROJECT_ROOT)
|
|
old_presets_dir = project_root / "molecule" / "presets"
|
|
if old_presets_dir.exists():
|
|
presets_dir = old_presets_dir
|
|
print(f"⚠️ Используется старый путь: {presets_dir}")
|
|
|
|
k8s_presets_dir = presets_dir / "k8s"
|
|
|
|
print(f"📁 Поиск пресетов в: {presets_dir}")
|
|
|
|
loaded_count = 0
|
|
skipped_count = 0
|
|
error_count = 0
|
|
|
|
# Функция для импорта одного пресета
|
|
def import_preset(preset_file, category='main'):
|
|
try:
|
|
with open(preset_file) as f:
|
|
content = f.read()
|
|
preset_data = yaml.safe_load(content) or {}
|
|
|
|
# Извлечение описания из комментария
|
|
description = None
|
|
for line in content.split('\n'):
|
|
if line.strip().startswith('#description:'):
|
|
description = line.split('#description:')[1].strip()
|
|
break
|
|
|
|
# Проверка существования в БД
|
|
result = connection.execute(
|
|
text("SELECT id FROM presets WHERE name = :name"),
|
|
{"name": preset_file.stem}
|
|
)
|
|
if result.fetchone():
|
|
print(f"⏭️ Пропущен (уже существует): {preset_file.stem}")
|
|
return 'skipped'
|
|
|
|
# Вставка в БД
|
|
# Преобразуем dict/list в JSON строки для PostgreSQL
|
|
hosts_json = json.dumps(preset_data.get('hosts', []))
|
|
images_json = json.dumps(preset_data.get('images', {}))
|
|
systemd_defaults_json = json.dumps(preset_data.get('systemd_defaults', {}))
|
|
kind_clusters_json = json.dumps(preset_data.get('kind_clusters', []))
|
|
|
|
connection.execute(
|
|
text("""
|
|
INSERT INTO presets (name, category, description, content, docker_network, hosts, images, systemd_defaults, kind_clusters, created_at, updated_at)
|
|
VALUES (:name, :category, :description, :content, :docker_network, CAST(:hosts AS jsonb), CAST(:images AS jsonb), CAST(:systemd_defaults AS jsonb), CAST(:kind_clusters AS jsonb), :created_at, :updated_at)
|
|
"""),
|
|
{
|
|
'name': preset_file.stem,
|
|
'category': category,
|
|
'description': description,
|
|
'content': content,
|
|
'docker_network': preset_data.get('docker_network'),
|
|
'hosts': hosts_json,
|
|
'images': images_json,
|
|
'systemd_defaults': systemd_defaults_json,
|
|
'kind_clusters': kind_clusters_json,
|
|
'created_at': datetime.utcnow(),
|
|
'updated_at': datetime.utcnow()
|
|
}
|
|
)
|
|
connection.commit()
|
|
print(f"✅ Загружен: {preset_file.stem}")
|
|
return 'loaded'
|
|
except Exception as e:
|
|
print(f"❌ Ошибка при загрузке {preset_file.name}: {e}")
|
|
return 'error'
|
|
|
|
# Основные preset'ы из корня папки presets
|
|
if presets_dir.exists():
|
|
for preset_file in presets_dir.glob("*.yml"):
|
|
if preset_file.name == "deploy.yml":
|
|
continue
|
|
result = import_preset(preset_file, category='main')
|
|
if result == 'loaded':
|
|
loaded_count += 1
|
|
elif result == 'skipped':
|
|
skipped_count += 1
|
|
elif result == 'error':
|
|
error_count += 1
|
|
|
|
# Пресеты из папки examples
|
|
examples_dir = presets_dir / "examples"
|
|
if examples_dir.exists():
|
|
print(f"📁 Поиск пресетов в examples: {examples_dir}")
|
|
for preset_file in examples_dir.glob("*.yml"):
|
|
result = import_preset(preset_file, category='main')
|
|
if result == 'loaded':
|
|
loaded_count += 1
|
|
elif result == 'skipped':
|
|
skipped_count += 1
|
|
elif result == 'error':
|
|
error_count += 1
|
|
|
|
# K8s preset'ы
|
|
if k8s_presets_dir.exists():
|
|
for preset_file in k8s_presets_dir.glob("*.yml"):
|
|
try:
|
|
with open(preset_file) as f:
|
|
content = f.read()
|
|
preset_data = yaml.safe_load(content) or {}
|
|
|
|
# Извлечение описания из комментария
|
|
description = None
|
|
for line in content.split('\n'):
|
|
if line.strip().startswith('#description:'):
|
|
description = line.split('#description:')[1].strip()
|
|
break
|
|
|
|
# Проверка существования в БД
|
|
result = connection.execute(
|
|
text("SELECT id FROM presets WHERE name = :name"),
|
|
{"name": preset_file.stem}
|
|
)
|
|
if result.fetchone():
|
|
print(f"⏭️ Пропущен (уже существует): {preset_file.stem}")
|
|
skipped_count += 1
|
|
continue
|
|
|
|
# Вставка в БД
|
|
# Преобразуем dict/list в JSON строки для PostgreSQL
|
|
hosts_json = json.dumps(preset_data.get('hosts', []))
|
|
images_json = json.dumps(preset_data.get('images', {}))
|
|
systemd_defaults_json = json.dumps(preset_data.get('systemd_defaults', {}))
|
|
kind_clusters_json = json.dumps(preset_data.get('kind_clusters', []))
|
|
|
|
connection.execute(
|
|
text("""
|
|
INSERT INTO presets (name, category, description, content, docker_network, hosts, images, systemd_defaults, kind_clusters, created_at, updated_at)
|
|
VALUES (:name, :category, :description, :content, :docker_network, CAST(:hosts AS jsonb), CAST(:images AS jsonb), CAST(:systemd_defaults AS jsonb), CAST(:kind_clusters AS jsonb), :created_at, :updated_at)
|
|
"""),
|
|
{
|
|
'name': preset_file.stem,
|
|
'category': 'k8s',
|
|
'description': description,
|
|
'content': content,
|
|
'docker_network': preset_data.get('docker_network'),
|
|
'hosts': hosts_json,
|
|
'images': images_json,
|
|
'systemd_defaults': systemd_defaults_json,
|
|
'kind_clusters': kind_clusters_json,
|
|
'created_at': datetime.utcnow(),
|
|
'updated_at': datetime.utcnow()
|
|
}
|
|
)
|
|
connection.commit()
|
|
print(f"✅ Загружен: {preset_file.stem} (k8s)")
|
|
loaded_count += 1
|
|
except Exception as e:
|
|
print(f"❌ Ошибка при загрузке k8s preset {preset_file.name}: {e}")
|
|
error_count += 1
|
|
|
|
print(f"\n📊 Итого:")
|
|
print(f" ✅ Загружено: {loaded_count}")
|
|
print(f" ⏭️ Пропущено: {skipped_count}")
|
|
print(f" ❌ Ошибок: {error_count}")
|
|
|
|
finally:
|
|
connection.close()
|
|
engine.dispose()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
load_presets()
|