mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-11-10 05:53:05 +09:00
fix(backups): degrade gracefully when the backup dir is not accessible
This commit is contained in:
1 parent
dd9003d458
commit
9b93cb34ef
3 files changed
+42
-2
No files matched your search
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
import os
|
||||
from flask import Blueprint, request, jsonify
|
||||
from flask_jwt_extended import jwt_required
|
||||
@@ -11,6 +12,10 @@ from app.exceptions import field_required, not_found
|
||||
from app.api._request import json_object
|
||||
|
||||
backups_bp = Blueprint('backups', __name__)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_STORAGE_UNAVAILABLE = ('Backup storage is not accessible: the panel cannot create or read '
|
||||
'its backup directory. Check its ownership and permissions.')
|
||||
|
||||
|
||||
# UI-facing metadata for the CORE target types. Extension kinds
|
||||
@@ -62,7 +67,12 @@ def list_target_types():
|
||||
def list_backups():
|
||||
"""List all backups."""
|
||||
backup_type = request.args.get('type')
|
||||
backups = BackupService.list_backups(backup_type)
|
||||
try:
|
||||
backups = BackupService.list_backups(backup_type)
|
||||
except OSError:
|
||||
# e.g. PermissionError creating /var/backups/serverkit: keep the page usable.
|
||||
logger.exception('Backup directory is not accessible')
|
||||
return jsonify({'backups': [], 'warning': _STORAGE_UNAVAILABLE}), 200
|
||||
return jsonify({'backups': backups}), 200
|
||||
|
||||
|
||||
@@ -70,7 +80,14 @@ def list_backups():
|
||||
@admin_required
|
||||
def get_stats():
|
||||
"""Get backup statistics."""
|
||||
stats = BackupService.get_backup_stats()
|
||||
try:
|
||||
stats = BackupService.get_backup_stats()
|
||||
except OSError:
|
||||
logger.exception('Backup directory is not accessible')
|
||||
stats = {'total_backups': 0, 'application_backups': 0, 'database_backups': 0,
|
||||
'file_backups': 0, 'total_size': 0, 'total_size_human': '0 B',
|
||||
'remote_count': 0, 'remote_size': 0, 'remote_size_human': '0 B',
|
||||
'warning': _STORAGE_UNAVAILABLE}
|
||||
return jsonify(stats), 200
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
"""GET /backups must not 500 when the backup directory cannot be created."""
|
||||
import pytest
|
||||
|
||||
from app.services.backup_service import BackupService
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def unwritable(monkeypatch):
|
||||
def deny():
|
||||
raise PermissionError(13, 'Permission denied', '/var/backups/serverkit')
|
||||
monkeypatch.setattr(BackupService, 'ensure_backup_dirs', deny)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('path', ['/api/v1/backups', '/api/v1/backups/stats'])
|
||||
def test_get_degrades_with_a_warning(client, auth_headers, unwritable, path):
|
||||
resp = client.get(path, headers=auth_headers)
|
||||
|
||||
assert resp.status_code == 200
|
||||
body = resp.get_json()
|
||||
assert 'not accessible' in body['warning']
|
||||
assert '/var/backups' not in body['warning']
|
||||
assert body.get('backups', []) == []
|
||||
@@ -216,6 +216,7 @@ const Backups = () => {
|
||||
]);
|
||||
|
||||
setBackups(backupsRes.backups || []);
|
||||
if (backupsRes.warning) setError(backupsRes.warning);
|
||||
setStats(statsRes);
|
||||
setConfig(configRes);
|
||||
if (refreshSchedules) await reloadSchedules();
|
||||
|
||||
Reference in new issue
Block a user