115 lines
5.2 KiB
Python
115 lines
5.2 KiB
Python
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
|
||
#init_oracle_client() Если работает нужно убрать!
|
||
|
||
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")
|
||
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")
|
||
|
||
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:
|
||
# Проверка является ли запись дублирующей
|
||
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}')
|