from os import environ import hvac import hvac.exceptions from oracledb import Error, create_pool, init_oracle_client import write_error_to_log init_oracle_client() class SimpleDB: def __init__(self): self._create_db_pool_from_vault() self.pool def _handle_vault_exception(self, e: Exception, message: str): """ Обработка исключений Vault с возвратом понятного сообщения. """ print(message) if isinstance(e, hvac.exceptions.InvalidPath): raise hvac.exceptions.InvalidPath("Database configuration not found in Vault") elif isinstance(e, hvac.exceptions.Forbidden): raise hvac.exceptions.Forbidden("Permission denied to access Vault secrets") elif isinstance(e, hvac.exceptions.Unauthorized): raise hvac.exceptions.Unauthorized("Invalid Vault token") elif isinstance(e, hvac.exceptions.VaultError): raise hvac.exceptions.VaultError(f"Vault secret retrieval failed: {e}") elif isinstance(e, hvac.exceptions.InvalidRequest): raise hvac.exceptions.InvalidRequest(f"Missing database parameter in Vault response: {e}") elif isinstance(e, hvac.exceptions.VaultDown): raise hvac.exceptions.VaultDown(f"Database server not available: {e}") else: raise Exception (f'Unexpected error reading from Vault: {e}') def _create_db_pool_from_vault(self): """ Подключение к Vault и создание пула соеденения. """ try: # Подключение к Vault client = hvac.Client( url='https://vlt.dataekb.ru:8222', token=environ.get('VAULT_TOKEN'), ) except Exception as e: self._handle_vault_exception(e, "Ошибка при создание покдлючения c Vault") # Отладочная информация print(f"Authenticated: {client.is_authenticated()}") print(f"Token: {environ.get('VAULT_TOKEN')}") # Конец отладочной информации # Проверяем аутентификацию #if not client.is_authenticated(): # raise Exception("Vault authentication failed") 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, "Ошибка чтение скретов из Vault") print(e, "Ошибка чтение скретов из 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, "Ошибка при создание пула для подключение к 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, "No data to process") try: with self.pool.acquire() as connection: with connection.cursor() as cursor: for dict_argument_bd in list_data: print("Отправляемые аргрументы: ", dict_argument_bd) print("Типы данных: ", *map(type, dict_argument_bd.values())) 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: print(e) # нужно убрать, проверка работат ли. # Проверка является ли запись дублирующей if 'ORA-00001' in str(e): continue # В остальных случаях запись ошибки и пропуск данных. else: error_message = f"ERROR_DB-WRITE: {e} DATA: {dict_argument_bd}" # Запись логов write_error_to_log.write_to_log(error_message) continue except Exception as e: error_message = f"ERROR_DB-GLOBAL: {e}" write_error_to_log.write_to_log(error_message) raise Error(f'Неожиданная ошибка: {e}')