fix(backup): retirer users.sqlite du suivi git, logging, test restore CLI, garde snapshot (#89)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+11
-3
@@ -1,4 +1,5 @@
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
@@ -7,6 +8,8 @@ from src.backup import service
|
||||
from src.backup.config import load_config
|
||||
from src.backup.storage import S3Storage
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def main(argv=None, env=None, storage=None) -> int:
|
||||
env = env if env is not None else os.environ
|
||||
@@ -24,9 +27,14 @@ def main(argv=None, env=None, storage=None) -> int:
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
if args.cmd == "backup":
|
||||
key = service.run_backup(config, storage, now)
|
||||
print(f"sauvegarde créée : {key}")
|
||||
return 0
|
||||
try:
|
||||
key = service.run_backup(config, storage, now)
|
||||
print(f"sauvegarde créée : {key}")
|
||||
return 0
|
||||
except Exception as exc:
|
||||
logger.error("Échec de la sauvegarde : %s", exc, exc_info=True)
|
||||
print(f"Erreur : {exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
if args.cmd == "list":
|
||||
backups = service.list_backups(config, storage)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
from datetime import datetime
|
||||
@@ -8,6 +9,8 @@ from src.backup.config import BackupConfig
|
||||
from src.backup.rotation import select_retained
|
||||
from src.backup.storage import Storage
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _dated_keys(storage: Storage, prefix: str) -> list[tuple[str, datetime]]:
|
||||
dated: list[tuple[str, datetime]] = []
|
||||
@@ -30,6 +33,7 @@ def run_backup(config: BackupConfig, storage: Storage, now: datetime) -> str:
|
||||
for k, ts in dated:
|
||||
if ts not in retained:
|
||||
storage.delete(k)
|
||||
logger.info("Sauvegarde créée : %s", key)
|
||||
return key
|
||||
|
||||
|
||||
@@ -57,6 +61,7 @@ def restore(config: BackupConfig, storage: Storage, key: str, now: datetime) ->
|
||||
backup_copy.write_bytes(db_path.read_bytes())
|
||||
os.replace(tmp_path, db_path)
|
||||
except Exception:
|
||||
logger.error("Échec de la restauration depuis %s", key, exc_info=True)
|
||||
tmp_path.unlink(missing_ok=True)
|
||||
raise
|
||||
return backup_copy
|
||||
|
||||
@@ -5,6 +5,8 @@ from pathlib import Path
|
||||
|
||||
|
||||
def make_snapshot(db_path: Path) -> bytes:
|
||||
if not db_path.exists():
|
||||
raise FileNotFoundError(f"Base de données introuvable : {db_path}")
|
||||
with tempfile.NamedTemporaryFile(suffix=".sqlite", delete=False) as tmp:
|
||||
tmp_path = Path(tmp.name)
|
||||
try:
|
||||
|
||||
@@ -14,8 +14,13 @@ class Storage(Protocol):
|
||||
|
||||
class S3Storage:
|
||||
def __init__(
|
||||
self, bucket, endpoint_url, access_key, secret_key, region="us-east-1"
|
||||
):
|
||||
self,
|
||||
bucket: str,
|
||||
endpoint_url: str | None,
|
||||
access_key: str,
|
||||
secret_key: str,
|
||||
region: str = "us-east-1",
|
||||
) -> None:
|
||||
self._bucket = bucket
|
||||
self._client = boto3.client(
|
||||
"s3",
|
||||
|
||||
Reference in New Issue
Block a user