init refactor
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,4 +1,6 @@
|
|||||||
*__pycache__*
|
*__pycache__*
|
||||||
*.ps1
|
*.ps1
|
||||||
keyring passwords.py
|
keyring passwords.py
|
||||||
logs
|
*logs*
|
||||||
|
*\.github*
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ from superset_tool.client import SupersetClient
|
|||||||
from superset_tool.utils.logger import SupersetLogger
|
from superset_tool.utils.logger import SupersetLogger
|
||||||
from superset_tool.exceptions import AuthenticationError, SupersetAPIError, NetworkError, DashboardNotFoundError
|
from superset_tool.exceptions import AuthenticationError, SupersetAPIError, NetworkError, DashboardNotFoundError
|
||||||
from superset_tool.utils.fileio import save_and_unpack_dashboard, update_yamls, create_dashboard_export, create_temp_file, read_dashboard_from_disk
|
from superset_tool.utils.fileio import save_and_unpack_dashboard, update_yamls, create_dashboard_export, create_temp_file, read_dashboard_from_disk
|
||||||
|
from superset_tool.utils.init_clients import setup_clients
|
||||||
|
|
||||||
# [IMPORTS] Стандартная библиотека
|
# [IMPORTS] Стандартная библиотека
|
||||||
import os
|
import os
|
||||||
@@ -84,66 +85,30 @@ database_config_gp = {
|
|||||||
}
|
}
|
||||||
logger.debug("[CONFIG] Конфигурация Greenplum загружена.")
|
logger.debug("[CONFIG] Конфигурация Greenplum загружена.")
|
||||||
|
|
||||||
# [CONFIG] Конфигурация Superset API для Dev окружения
|
# [ANCHOR] CLIENT_SETUP
|
||||||
dev_config = SupersetConfig(
|
clients = setup_clients(logger)
|
||||||
base_url="https://devta.bi.dwh.rusal.com/api/v1",
|
|
||||||
auth={
|
|
||||||
"provider": "db",
|
|
||||||
"username": "migrate_user",
|
|
||||||
"password": keyring.get_password("system", "dev migrate"),
|
|
||||||
"refresh": True
|
|
||||||
},
|
|
||||||
logger=logger,
|
|
||||||
verify_ssl=False
|
|
||||||
)
|
|
||||||
logger.debug(f"[CONFIG] Dev SupersetConfig создан для {dev_config.base_url}")
|
|
||||||
|
|
||||||
# [CONFIG] Конфигурация Superset API для Prod окружения
|
|
||||||
prod_config = SupersetConfig(
|
|
||||||
base_url="https://prodta.bi.dwh.rusal.com/api/v1",
|
|
||||||
auth={
|
|
||||||
"provider": "db",
|
|
||||||
"username": "migrate_user",
|
|
||||||
"password": keyring.get_password("system", "prod migrate"),
|
|
||||||
"refresh": True
|
|
||||||
},
|
|
||||||
logger=logger,
|
|
||||||
verify_ssl=False
|
|
||||||
)
|
|
||||||
logger.debug(f"[CONFIG] Prod SupersetConfig создан для {prod_config.base_url}")
|
|
||||||
|
|
||||||
# [CONFIG] Конфигурация Superset API для Sandbox окружения
|
|
||||||
sandbox_config = SupersetConfig(
|
|
||||||
base_url="https://sandboxta.bi.dwh.rusal.com/api/v1",
|
|
||||||
auth={
|
|
||||||
"provider": "db",
|
|
||||||
"username": "migrate_user",
|
|
||||||
"password": keyring.get_password("system", "sandbox migrate"),
|
|
||||||
"refresh": True
|
|
||||||
},
|
|
||||||
logger=logger,
|
|
||||||
verify_ssl=False
|
|
||||||
)
|
|
||||||
logger.debug(f"[CONFIG] Sandbox SupersetConfig создан для {sandbox_config.base_url}")
|
|
||||||
|
|
||||||
# [INIT] Инициализация клиентов Superset API
|
|
||||||
# @invariant: Все клиенты должны быть успешно инициализированы для дальнейшей работы.
|
|
||||||
try:
|
|
||||||
dev_client = SupersetClient(dev_config)
|
|
||||||
sandbox_client = SupersetClient(sandbox_config)
|
|
||||||
prod_client = SupersetClient(prod_config) # Не используется в текущем flow, но инициализирован.
|
|
||||||
logger.info("[COHERENCE_CHECK_PASSED] Клиенты Superset успешно инициализированы.")
|
|
||||||
except Exception as e:
|
|
||||||
logger.critical(f"[CRITICAL] Ошибка инициализации клиентов Superset: {str(e)}", exc_info=True)
|
|
||||||
exit(1) # Выход из скрипта при критической ошибке инициализации
|
|
||||||
|
|
||||||
# [CONFIG] Определение исходного и целевого клиентов для миграции
|
# [CONFIG] Определение исходного и целевого клиентов для миграции
|
||||||
# [COHERENCE_NOTE] Эти переменные задают конкретную миграцию. Для параметризации можно использовать аргументы командной строки.
|
# [COHERENCE_NOTE] Эти переменные задают конкретную миграцию. Для параметризации можно использовать аргументы командной строки.
|
||||||
from_c = sandbox_client # Источник миграции
|
from_c = clients["sbx"] # Источник миграции
|
||||||
to_c = dev_client # Цель миграции
|
to_c = clients["preprod"] # Цель миграции
|
||||||
dashboard_slug = "FI0060" # Идентификатор дашборда для миграции
|
dashboard_slug = "FI0060" # Идентификатор дашборда для миграции
|
||||||
# dashboard_id = 53 # ID не нужен, если есть slug
|
# dashboard_id = 53 # ID не нужен, если есть slug
|
||||||
|
|
||||||
|
|
||||||
|
# [CONTRACT]
|
||||||
|
# Описание: Мигрирует один дашборд с from_c на to_c.
|
||||||
|
# @pre:
|
||||||
|
# - from_c и to_c должны быть инициализированы.
|
||||||
|
# @post:
|
||||||
|
# - Дашборд с from_c успешно экспортирован и импортирован в to_c.
|
||||||
|
# @raise:
|
||||||
|
# - Exception: В случае ошибки экспорта или импорта.
|
||||||
|
def migrate_dashboard (dashboard_slug=dashboard_slug,
|
||||||
|
from_c = from_c,
|
||||||
|
to_c = to_c,
|
||||||
|
logger=logger,
|
||||||
|
update_db_yaml=False):
|
||||||
|
|
||||||
logger.info(f"[INFO] Конфигурация миграции: From '{from_c.config.base_url}' To '{to_c.config.base_url}' for dashboard slug '{dashboard_slug}'")
|
logger.info(f"[INFO] Конфигурация миграции: From '{from_c.config.base_url}' To '{to_c.config.base_url}' for dashboard slug '{dashboard_slug}'")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -181,6 +146,7 @@ try:
|
|||||||
|
|
||||||
# [ANCHOR] UPDATE_YAML_CONFIGS
|
# [ANCHOR] UPDATE_YAML_CONFIGS
|
||||||
# Обновление конфигураций баз данных в YAML-файлах
|
# Обновление конфигураций баз данных в YAML-файлах
|
||||||
|
if update_db_yaml:
|
||||||
source_path = unpacked_path / Path(filename).stem # Путь к распакованному содержимому дашборда
|
source_path = unpacked_path / Path(filename).stem # Путь к распакованному содержимому дашборда
|
||||||
db_configs_to_apply = [database_config_click, database_config_gp]
|
db_configs_to_apply = [database_config_click, database_config_gp]
|
||||||
logger.info(f"[INFO] Применение трансформаций баз данных к YAML файлам в {source_path}...")
|
logger.info(f"[INFO] Применение трансформаций баз данных к YAML файлам в {source_path}...")
|
||||||
@@ -193,7 +159,8 @@ try:
|
|||||||
logger.info(f"[INFO] Создание нового ZIP-архива для импорта: {temp_zip}")
|
logger.info(f"[INFO] Создание нового ZIP-архива для импорта: {temp_zip}")
|
||||||
create_dashboard_export(temp_zip, [source_path], logger=logger)
|
create_dashboard_export(temp_zip, [source_path], logger=logger)
|
||||||
logger.info("[INFO] Новый ZIP-архив дашборда готов к импорту.")
|
logger.info("[INFO] Новый ZIP-архив дашборда готов к импорту.")
|
||||||
|
else:
|
||||||
|
temp_zip = zip_path
|
||||||
# [ANCHOR] IMPORT_DASHBOARD
|
# [ANCHOR] IMPORT_DASHBOARD
|
||||||
# Импорт обновленного дашборда в целевое окружение
|
# Импорт обновленного дашборда в целевое окружение
|
||||||
logger.info(f"[INFO] Запуск импорта дашборда в целевое окружение {to_c.config.base_url}...")
|
logger.info(f"[INFO] Запуск импорта дашборда в целевое окружение {to_c.config.base_url}...")
|
||||||
@@ -202,9 +169,42 @@ try:
|
|||||||
|
|
||||||
except (AuthenticationError, SupersetAPIError, NetworkError, DashboardNotFoundError) as e:
|
except (AuthenticationError, SupersetAPIError, NetworkError, DashboardNotFoundError) as e:
|
||||||
logger.error(f"[ERROR] Ошибка миграции дашборда: {str(e)}", exc_info=True, extra=e.context)
|
logger.error(f"[ERROR] Ошибка миграции дашборда: {str(e)}", exc_info=True, extra=e.context)
|
||||||
exit(1)
|
# exit(1)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.critical(f"[CRITICAL] Фатальная и необработанная ошибка в скрипте миграции: {str(e)}", exc_info=True)
|
logger.critical(f"[CRITICAL] Фатальная и необработанная ошибка в скрипте миграции: {str(e)}", exc_info=True)
|
||||||
exit(1)
|
# exit(1)
|
||||||
|
|
||||||
logger.info("[INFO] Процесс миграции завершен.")
|
logger.info("[INFO] Процесс миграции завершен.")
|
||||||
|
|
||||||
|
# [CONTRACT]
|
||||||
|
# Описание: Мигрирует все дашборды с from_c на to_c.
|
||||||
|
# @pre:
|
||||||
|
# - from_c и to_c должны быть инициализированы.
|
||||||
|
# @post:
|
||||||
|
# - Все дашборды с from_c успешно экспортированы и импортированы в to_c.
|
||||||
|
# @raise:
|
||||||
|
# - Exception: В случае ошибки экспорта или импорта.
|
||||||
|
def migrate_all_dashboards(from_c: SupersetClient, to_c: SupersetClient,logger=logger) -> None:
|
||||||
|
# [ACTION] Получение списка всех дашбордов из исходного окружения.
|
||||||
|
logger.info(f"[ACTION] Получение списка всех дашбордов из '{from_c.config.base_url}'")
|
||||||
|
total_dashboards, dashboards = from_c.get_dashboards()
|
||||||
|
logger.info(f"[INFO] Найдено {total_dashboards} дашбордов для миграции.")
|
||||||
|
|
||||||
|
# [ACTION] Итерация по всем дашбордам и миграция каждого из них.
|
||||||
|
for dashboard in dashboards:
|
||||||
|
dashboard_id = dashboard["id"]
|
||||||
|
dashboard_slug = dashboard["slug"]
|
||||||
|
dashboard_title = dashboard["dashboard_title"]
|
||||||
|
logger.info(f"[INFO] Начало миграции дашборда '{dashboard_title}' (ID: {dashboard_id}, Slug: {dashboard_slug}).")
|
||||||
|
if dashboard_slug:
|
||||||
|
try:
|
||||||
|
migrate_dashboard(dashboard_slug=dashboard_slug,from_c=from_c,to_c=to_c,logger=logger)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[ERROR] Ошибка миграции дашборда: {str(e)}", exc_info=True, extra=e.context)
|
||||||
|
else:
|
||||||
|
logger.info(f"[INFO] Пропуск '{dashboard_title}' (ID: {dashboard_id}, Slug: {dashboard_slug}). Пустой SLUG")
|
||||||
|
|
||||||
|
logger.info(f"[INFO] Миграция всех дашбордов с '{from_c.config.base_url}' на '{to_c.config.base_url}' завершена.")
|
||||||
|
|
||||||
|
# [ACTION] Вызов функции миграции
|
||||||
|
migrate_all_dashboards(from_c, to_c)
|
||||||
100
superset_tool/utils/init_clients.py
Normal file
100
superset_tool/utils/init_clients.py
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# [MODULE] Superset Init clients
|
||||||
|
# @contract: Автоматизирует процесс инициализации клиентов для использования скриптами.
|
||||||
|
# @semantic_layers:
|
||||||
|
# 1. Инициализация логгера и клиентов Superset.
|
||||||
|
# @coherence:
|
||||||
|
# - Использует `SupersetClient` для взаимодействия с API Superset.
|
||||||
|
# - Использует `SupersetLogger` для централизованного логирования.
|
||||||
|
# - Интегрируется с `keyring` для безопасного хранения паролей.
|
||||||
|
|
||||||
|
# [IMPORTS] Стандартная библиотека
|
||||||
|
import logging
|
||||||
|
from datetime import datetime
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# [IMPORTS] Сторонние библиотеки
|
||||||
|
import keyring
|
||||||
|
|
||||||
|
# [IMPORTS] Локальные модули
|
||||||
|
from superset_tool.models import SupersetConfig
|
||||||
|
from superset_tool.client import SupersetClient
|
||||||
|
from superset_tool.utils.logger import SupersetLogger
|
||||||
|
|
||||||
|
|
||||||
|
# [FUNCTION] setup_clients
|
||||||
|
# @contract: Инициализирует и возвращает SupersetClient для каждого заданного окружения.
|
||||||
|
# @pre:
|
||||||
|
# - `keyring` должен содержать необходимые пароли для "dev migrate", "prod migrate", "sandbox migrate".
|
||||||
|
# - `logger` должен быть инициализирован.
|
||||||
|
# @post:
|
||||||
|
# - Возвращает словарь {env_name: SupersetClient_instance}.
|
||||||
|
# - Логирует успешную инициализацию или ошибку.
|
||||||
|
# @raise:
|
||||||
|
# - `Exception`: При любой ошибке в процессе инициализации клиентов (например, отсутствие пароля в keyring, проблемы с сетью при первой аутентификации).
|
||||||
|
def setup_clients(logger: SupersetLogger):
|
||||||
|
"""Инициализация клиентов для разных окружений"""
|
||||||
|
# [ANCHOR] CLIENTS_INITIALIZATION
|
||||||
|
clients = {}
|
||||||
|
try:
|
||||||
|
# [INFO] Инициализация конфигурации для Dev
|
||||||
|
dev_config = SupersetConfig(
|
||||||
|
base_url="https://devta.bi.dwh.rusal.com/api/v1",
|
||||||
|
auth={
|
||||||
|
"provider": "db",
|
||||||
|
"username": "migrate_user",
|
||||||
|
"password": keyring.get_password("system", "dev migrate"),
|
||||||
|
"refresh": True
|
||||||
|
},
|
||||||
|
verify_ssl=False
|
||||||
|
)
|
||||||
|
# [DEBUG] Dev config created: {dev_config.base_url}
|
||||||
|
|
||||||
|
# [INFO] Инициализация конфигурации для Prod
|
||||||
|
prod_config = SupersetConfig(
|
||||||
|
base_url="https://prodta.bi.dwh.rusal.com/api/v1",
|
||||||
|
auth={
|
||||||
|
"provider": "db",
|
||||||
|
"username": "migrate_user",
|
||||||
|
"password": keyring.get_password("system", "prod migrate"),
|
||||||
|
"refresh": True
|
||||||
|
},
|
||||||
|
verify_ssl=False
|
||||||
|
)
|
||||||
|
# [DEBUG] Prod config created: {prod_config.base_url}
|
||||||
|
|
||||||
|
# [INFO] Инициализация конфигурации для Sandbox
|
||||||
|
sandbox_config = SupersetConfig(
|
||||||
|
base_url="https://sandboxta.bi.dwh.rusal.com/api/v1",
|
||||||
|
auth={
|
||||||
|
"provider": "db",
|
||||||
|
"username": "migrate_user",
|
||||||
|
"password": keyring.get_password("system", "sandbox migrate"),
|
||||||
|
"refresh": True
|
||||||
|
},
|
||||||
|
verify_ssl=False
|
||||||
|
)
|
||||||
|
# [DEBUG] Sandbox config created: {sandbox_config.base_url}
|
||||||
|
|
||||||
|
# [INFO] Инициализация конфигурации для Preprod
|
||||||
|
preprod_config = SupersetConfig(
|
||||||
|
base_url="https://preprodta.bi.dwh.rusal.com/api/v1",
|
||||||
|
auth={
|
||||||
|
"provider": "db",
|
||||||
|
"username": "migrate_user",
|
||||||
|
"password": keyring.get_password("system", "preprod migrate"),
|
||||||
|
"refresh": True
|
||||||
|
},
|
||||||
|
verify_ssl=False
|
||||||
|
)
|
||||||
|
# [DEBUG] Sandbox config created: {sandbox_config.base_url}
|
||||||
|
|
||||||
|
# [INFO] Создание экземпляров SupersetClient
|
||||||
|
clients['dev'] = SupersetClient(dev_config, logger)
|
||||||
|
clients['sbx'] = SupersetClient(sandbox_config,logger)
|
||||||
|
clients['prod'] = SupersetClient(prod_config,logger)
|
||||||
|
clients['preprod'] = SupersetClient(preprod_config,logger)
|
||||||
|
logger.info("[COHERENCE_CHECK_PASSED] Клиенты для окружений успешно инициализированы", extra={"envs": list(clients.keys())})
|
||||||
|
return clients
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[ERROR] Ошибка инициализации клиентов: {str(e)}", exc_info=True)
|
||||||
|
raise
|
||||||
Reference in New Issue
Block a user