add: read args & parse config
This commit is contained in:
parent
327e0a55e9
commit
4a81ed04a0
31
config/sample.yaml
Normal file
31
config/sample.yaml
Normal file
@ -0,0 +1,31 @@
|
||||
# Пример конфигурационного файла для PGanec
|
||||
|
||||
servers:
|
||||
- name: "PostgreSQL в k3s"
|
||||
host: "postrges.local"
|
||||
port: 5432
|
||||
user: "postgres"
|
||||
password: "****" # Здесь должен быть ваш пароль
|
||||
|
||||
- name: "PostgreSQL в Synology DS1522+ (Docker)"
|
||||
host: "ds1522.local"
|
||||
port: 5432
|
||||
user: "postgres"
|
||||
password: "****" # Здесь должен быть ваш пароль
|
||||
|
||||
- name: "Резервный сервер PostgreSQL"
|
||||
host: "192.168.1.200"
|
||||
port: 5432
|
||||
user: "postgres"
|
||||
password: "****" # Здесь должен быть ваш пароль
|
||||
|
||||
targets:
|
||||
- mountpoint: "/mnt/backups"
|
||||
label: "nas01"
|
||||
type: "nfs"
|
||||
|
||||
- mountpoint: "/mnt/usb"
|
||||
label: "usb-disk"
|
||||
type: "ext4"
|
||||
|
||||
|
11
src/pganec/_init_.py
Normal file
11
src/pganec/_init_.py
Normal file
@ -0,0 +1,11 @@
|
||||
"""
|
||||
PGanec - TUI для резервного копирования и восстановления баз данных PostgreSQL.
|
||||
|
||||
Основные возможности:
|
||||
- Конфигурация через YAML-файл для описания доступных серверов и мест хранения резервных копий.
|
||||
- Резервное копирование баз данных PostgreSQL.
|
||||
- Восстановление баз данных PostgreSQL.
|
||||
"""
|
||||
__version__ = "0.1.0"
|
||||
__author__ = "Sergey Erjemin"
|
||||
__license__ = "MIT"
|
63
src/pganec/config.py
Normal file
63
src/pganec/config.py
Normal file
@ -0,0 +1,63 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
import yaml
|
||||
from typing import Optional, Dict # Для Python < 3.9 используйте Dict, для Python 3.9+ можно просто dict
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class ConfigError(Exception):
|
||||
"""Базовый класс для ошибок конфигурации."""
|
||||
pass
|
||||
|
||||
class ConfigNotFoundError(ConfigError):
|
||||
"""Файл конфигурации не найден."""
|
||||
pass
|
||||
|
||||
class InvalidConfigFormatError(ConfigError):
|
||||
"""Ошибка формата YAML в конфигурации."""
|
||||
pass
|
||||
|
||||
|
||||
def load_config(path: str) -> Optional[Dict]:
|
||||
"""
|
||||
Загрузка конфигурации из YAML файла.
|
||||
Обрабатывает ошибки чтения файла и парсинга YAML.
|
||||
|
||||
:param path: Путь к файлу конфигурации.
|
||||
:return: Словарь с конфигурацией или None в случае ошибки.
|
||||
"""
|
||||
logger.debug(f"Попытка загрузки конфигурации из файла: `{path}`")
|
||||
try:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
config_data = yaml.safe_load(f)
|
||||
|
||||
# Проверим, что YAML действительно распарсился в словарь
|
||||
if not isinstance(config_data, dict):
|
||||
msg = f"Содержимое файла конфигурации `{path}` не является словарем. Тип: {type(config_data).__name__}."
|
||||
logger.error(msg)
|
||||
raise InvalidConfigFormatError(msg)
|
||||
|
||||
logger.info(msg=f"Конфигурация успешно загружена из `{path}`")
|
||||
return config_data
|
||||
|
||||
except FileNotFoundError:
|
||||
msg=f"Файл конфигурации не найден: `{path}`"
|
||||
logger.error(msg)
|
||||
raise ConfigNotFoundError(msg) from None # from None подавляет цепочку исключений
|
||||
except yaml.YAMLError as e:
|
||||
# YAMLError - базовый класс для ошибок PyYAML (ошибки сканера, парсера и т.п.)
|
||||
msg = f"Ошибка парсинга YAML в файле `{path}`: {e}"
|
||||
logger.error(msg)
|
||||
raise InvalidConfigFormatError(msg) from e
|
||||
except IOError as e:
|
||||
# IOError или OSError для других проблем с доступом к файлу (например, права доступа)
|
||||
msg = f"Ошибка ввода-вывода при чтении файла `{path}`: {e}"
|
||||
logger.error(msg)
|
||||
raise ConfigError(msg) from e # Общее исключение для других ошибок ввода-вывода
|
||||
except Exception as e:
|
||||
# Отлавливаем любые другие непредвиденные исключения
|
||||
logger.critical(
|
||||
msg=f"Непредвиденная ошибка при загрузке конфигурации из `{path}`: {e}",
|
||||
exc_info=True # Добавляет трассировку стека в лог для лучшей диагностики
|
||||
)
|
||||
raise ConfigError(f"Непредвиденная ошибка: {e}") from e
|
68
src/pganec/main.py
Normal file
68
src/pganec/main.py
Normal file
@ -0,0 +1,68 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import argparse
|
||||
import logging
|
||||
import sys
|
||||
from config import load_config, ConfigError, ConfigNotFoundError, InvalidConfigFormatError
|
||||
|
||||
# --- Настройки и инициирование логирования ---
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def print_hi(name):
|
||||
# Use a breakpoint in the code line below to debug your script.
|
||||
print(f'Hi, {name}') # Press ⌘F8 to toggle the breakpoint.
|
||||
|
||||
|
||||
# Press the green button in the gutter to run the script.
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="PGanec — TUI резервного копирования и восстановления баз PostgreSQL")
|
||||
parser.add_argument("-c", "--config", required=True,
|
||||
help="Путь к файлу конфигурации (YAML)")
|
||||
parser.add_argument("-d", "--debug-level", default="QUIET",
|
||||
help="Уровень отладки (QUIET, NOTSET, DEBUG, INFO, WARNING, ERROR, CRITICAL)")
|
||||
parser.add_argument("-l", "--loging", default="",
|
||||
help="Путь к файлу логирования (если не указан, логирование не будет вестись)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Настройка отладочных логов
|
||||
level_input_str = args.debug_level.upper()
|
||||
chosen_log_level = None
|
||||
if level_input_str == "QUIET": # Опция "QUIET"
|
||||
chosen_log_level = logging.CRITICAL + 1
|
||||
else:
|
||||
chosen_log_level = getattr(logging, level_input_str, None)
|
||||
if chosen_log_level is None:
|
||||
logger.warning(f"Неизвестный уровень отладки '{args.debug_level}'. Используется DEBUG.")
|
||||
chosen_log_level = logging.DEBUG
|
||||
|
||||
logging.basicConfig(
|
||||
level=chosen_log_level,
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(module)s.%(funcName)s:%(lineno)d - %(message)s"
|
||||
)
|
||||
logger.debug(f"Параметрами: {args}")
|
||||
logger.debug(f"Уровень: {chosen_log_level}")
|
||||
|
||||
# Загрузка конфигурации
|
||||
try:
|
||||
config = load_config(args.config)
|
||||
logger.info(f"Конфигурация успешно загружена: {config}")
|
||||
except ConfigNotFoundError:
|
||||
print(f"Ошибка: Файл конфигурации '{args.config}' не найден.", file=sys.stderr)
|
||||
# Возможно сюда стоит добавить TUI интерфейс для ввода (выбора) файла конфигурации...
|
||||
# Но так как ошибка может быть связана с правами доступа (например, TUI запущен от неправильного
|
||||
# пользователя), оставим идею "на-подумать", а пока просто завершим выполнение программы.
|
||||
sys.exit(1)
|
||||
except InvalidConfigFormatError as e:
|
||||
print(f"Ошибка: Файл конфигурации '{args.config}' имеет неверный формат. {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except ConfigError as e: # Общая ошибка конфигурации (должна быть последней в цепочке)
|
||||
print(f"Ошибка при загрузке конфигурации: {e}", file=sys.stderr)
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
print_hi('PyCharm')
|
||||
|
||||
# with open("config.yaml", "r") as f:
|
||||
# config = yaml.safe_load(f)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user