from os import environ import hvac import hvac.exceptions from oracledb import Error, create_pool, init_oracle_client import error_to_log init_oracle_client() class WorkingDB: def __init__(self): print('-'*60) print("Инициализация WorkingDB") self._create_db_pool_from_vault() self.pool print('-'*60) def _handle_vault_exception(self, e: Exception, message: str): """ Обработка исключений Vault с возвратом понятного сообщения. """ error_to_log.write_to_log(message) ind = {' '*4} if isinstance(e, hvac.exceptions.InvalidPath): raise hvac.exceptions.InvalidPath(f"{ind}Database configuration not found in Vault") elif isinstance(e, hvac.exceptions.Forbidden): raise hvac.exceptions.Forbidden(f"{ind}Permission denied to access Vault secrets") elif isinstance(e, hvac.exceptions.Unauthorized): raise hvac.exceptions.Unauthorized(f"{ind}Invalid Vault token") elif isinstance(e, hvac.exceptions.VaultError): raise hvac.exceptions.VaultError(f"{ind}Vault secret retrieval failed: {e}") elif isinstance(e, hvac.exceptions.InvalidRequest): raise hvac.exceptions.InvalidRequest(f"{ind}Missing database parameter in Vault response: {e}") elif isinstance(e, hvac.exceptions.VaultDown): raise hvac.exceptions.VaultDown(f"{ind}Database server not available: {e}") else: raise Exception (f'{ind}Unexpected error reading from Vault: {e}') def _create_db_pool_from_vault(self): """ Подключение к Vault и создание пула соеденения. """ try: # Подключение к Vault print(f"{' '*2}Подключение к Vault") client = hvac.Client( url='https://vlt.dataekb.ru:8222', token=environ.get('VAULT_TOKEN'), ) except Exception as e: self._handle_vault_exception(e, f"{' '*4}Ошибка при создание покдлючения c Vault") # Проверка авторизации в Vault print(f"{' '*4}Проверка авторизации") if not client.is_authenticated(): raise Exception(f"{' '*6}Не удалось автозоваться в Vault") else: print(f"{' '*6}Успешно") try: # Чтение секретов из Vault secret_read_response = client.secrets.kv.v2.read_secret_version( path='oracledb', mount_point='kv' ) except Exception as e: self._handle_vault_exception(e, f"{' '*4}Ошибка чтение скретов из Vault") try: # Создаем пул соединений self.pool = create_pool( user=secret_read_response['data']['data']['user'], password=secret_read_response['data']['data']['password'], dsn=secret_read_response['data']['data']['cs'], min=2, max=10, increment=1 ) except Exception as e: self._handle_vault_exception(e, f"{' '*2}Ошибка при создание пула для подключение к Oracle") def data_transfer_in_database(self, list_data: list): """ Передача данных в базу Процедура на вставку: P_RK_GOVERNMENT_REPORTS_INSERS ( ID IN NUMBER, ORGAN IN VARCHAR2, NAMES IN VARCHAR2, DATE_FROM in date, DATE_TO in date, VERS IN VARCHAR2) """ # Данные для БД не могут быть пустыми if not list_data: raise ValueError(list_data, "Данные для БД не могут быть пустыми") try: print(f"{' '*2}Отправка данных в бд") with self.pool.acquire() as connection: with connection.cursor() as cursor: for dict_argument_bd in list_data: # Просмотр отпавлямых арогументов for key, value in dict_argument_bd.items(): print('-'*40) print(f"{' '*4}Отправляемые аргументы - {key}: {value} -> {type(value)}") try: cursor.callproc('P_RK_GOVERNMENT_REPORTS_INSERS', [ dict_argument_bd['id'], dict_argument_bd['organ'], dict_argument_bd['names'], dict_argument_bd['date_from'], dict_argument_bd['date_to'], # Может быть None dict_argument_bd['ver'], ]) except Error as e: # Проверка является ли запись дублирующей if 'ORA-00001' in str(e): continue # В остальных случаях запись ошибки и пропуск данных. else: error_message = f"ERROR_DB-WRITE: {e} DATA: {dict_argument_bd}" # Запись логов error_to_log.write_to_log(error_message) continue except Exception as e: error_message = f"ERROR_DB-GLOBAL: {e}" error_to_log.write_to_log(error_message) raise Error(f'Неожиданная ошибка: {e}')