mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 19:01:39 -04:00
131 lines
5 KiB
Python
131 lines
5 KiB
Python
from sanic import response, Blueprint
|
|
from sanic.request import Request
|
|
from sanic_ext.extensions.openapi import openapi
|
|
|
|
from wrolpi import config_schema
|
|
from wrolpi.api_utils import json_response
|
|
from wrolpi.common import get_all_configs, get_config_by_file_name, DB_CONFIG_FILE_NAMES
|
|
from wrolpi.common import logger
|
|
from wrolpi.errors import InvalidConfig
|
|
|
|
config_bp = Blueprint('config', '/api/config')
|
|
|
|
|
|
@config_bp.get('/')
|
|
@openapi.description('Get the status (imported, valid, etc.) of all configs.')
|
|
@openapi.parameter('file_name', str, location='query')
|
|
def get_config(request: Request):
|
|
if file_name := request.args.get('file_name'):
|
|
config = get_config_by_file_name(file_name)
|
|
config_file = config.get_file()
|
|
config_text = config_file.read_text() if config_file.is_file() else None
|
|
return json_response(dict(config=config, config_text=config_text))
|
|
else:
|
|
configs = get_all_configs()
|
|
configs = {k: v.config_status() for k, v in configs.items()}
|
|
return json_response(dict(configs=configs))
|
|
|
|
|
|
@config_bp.post('/')
|
|
@openapi.parameter('file_name', str, location='query')
|
|
@openapi.definition(
|
|
description='Update the contents of a specific config.',
|
|
body=config_schema.ConfigUpdateRequest,
|
|
validate=True,
|
|
)
|
|
def post_config_update(request: Request, body: config_schema.ConfigUpdateRequest):
|
|
file_name, = request.args['file_name']
|
|
config = get_config_by_file_name(file_name)
|
|
config.update(body.config)
|
|
return response.empty()
|
|
|
|
|
|
@config_bp.post('/import')
|
|
@openapi.definition(
|
|
description='Import the contents of a specific config.',
|
|
body=config_schema.ConfigsRequest,
|
|
validate=True,
|
|
)
|
|
def post_config_import(_: Request, body: config_schema.ConfigsRequest):
|
|
config = get_config_by_file_name(body.file_name)
|
|
try:
|
|
config.import_config(send_events=True)
|
|
except Exception as e:
|
|
logger.error(f'Failed to import config: {body.file_name}', exc_info=e)
|
|
raise InvalidConfig(f'Failed to import config {body.file_name}')
|
|
|
|
return response.empty()
|
|
|
|
|
|
@config_bp.post('/dump')
|
|
@openapi.definition(
|
|
description="Dump the contents of a specific config to it's file.",
|
|
body=config_schema.ConfigsRequest,
|
|
validate=True,
|
|
)
|
|
def post_config_dump(_: Request, body: config_schema.ConfigsRequest):
|
|
config = get_config_by_file_name(body.file_name)
|
|
try:
|
|
config.dump_config(send_events=True, overwrite=body.overwrite)
|
|
except Exception as e:
|
|
logger.error(f'Failed to dump config: {body.file_name}', exc_info=e)
|
|
raise InvalidConfig(f'Failed to dump config {body.file_name}')
|
|
|
|
return response.empty()
|
|
|
|
|
|
@config_bp.get('/backups')
|
|
@openapi.description('Get available backup dates for a config file.')
|
|
@openapi.parameter('file_name', str, location='query')
|
|
def get_config_backups(request: Request):
|
|
file_name = request.args.get('file_name')
|
|
if not file_name:
|
|
raise InvalidConfig('file_name is required')
|
|
config = get_config_by_file_name(file_name)
|
|
if file_name not in DB_CONFIG_FILE_NAMES:
|
|
raise InvalidConfig(f'{file_name} does not support backup import')
|
|
dates = config.get_backup_dates()
|
|
return json_response(dict(dates=dates))
|
|
|
|
|
|
@config_bp.post('/backup/preview')
|
|
@openapi.definition(
|
|
description='Preview what a backup import would change.',
|
|
body=config_schema.ConfigBackupPreviewRequest,
|
|
validate=True,
|
|
)
|
|
def post_config_backup_preview(_: Request, body: config_schema.ConfigBackupPreviewRequest):
|
|
if body.mode not in ('merge', 'overwrite'):
|
|
raise InvalidConfig('mode must be "merge" or "overwrite"')
|
|
config = get_config_by_file_name(body.file_name)
|
|
if body.file_name not in DB_CONFIG_FILE_NAMES:
|
|
raise InvalidConfig(f'{body.file_name} does not support backup import')
|
|
backup_file = config._get_backup_file(body.backup_date)
|
|
if not backup_file.is_file():
|
|
raise InvalidConfig(f'Backup file not found for date {body.backup_date}')
|
|
preview = config.preview_backup_import(body.backup_date, body.mode)
|
|
return json_response(dict(preview=preview))
|
|
|
|
|
|
@config_bp.post('/backup/import')
|
|
@openapi.definition(
|
|
description='Import a backup config file.',
|
|
body=config_schema.ConfigBackupImportRequest,
|
|
validate=True,
|
|
)
|
|
def post_config_backup_import(_: Request, body: config_schema.ConfigBackupImportRequest):
|
|
if body.mode not in ('merge', 'overwrite'):
|
|
raise InvalidConfig('mode must be "merge" or "overwrite"')
|
|
config = get_config_by_file_name(body.file_name)
|
|
if body.file_name not in DB_CONFIG_FILE_NAMES:
|
|
raise InvalidConfig(f'{body.file_name} does not support backup import')
|
|
backup_file = config._get_backup_file(body.backup_date)
|
|
if not backup_file.is_file():
|
|
raise InvalidConfig(f'Backup file not found for date {body.backup_date}')
|
|
try:
|
|
config.import_backup(body.backup_date, body.mode, send_events=True)
|
|
except Exception as e:
|
|
logger.error(f'Failed to import backup: {body.file_name} {body.backup_date}', exc_info=e)
|
|
raise InvalidConfig(f'Failed to import backup {body.file_name}')
|
|
|
|
return response.empty()
|