132 lines
5.9 KiB
Python
132 lines
5.9 KiB
Python
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}')
|