|
|
@@ -24,40 +24,78 @@ def apply_retention(job, new_archive_name, backup_dir):
|
|
|
return deleted
|
|
|
|
|
|
|
|
|
-def _list_archives_for_job(job, backup_dir):
|
|
|
- """Liste les archives correspondant à ce job, triées par date (plus ancienne en premier)."""
|
|
|
- from flask import current_app
|
|
|
- instance = current_app.config["INSTANCE_NAME"]
|
|
|
-
|
|
|
+def _job_archive_prefix(job, instance_name):
|
|
|
+ """Retourne le préfixe des archives pour ce job (ex: jerry_nextcloud_)."""
|
|
|
if job.type == "ynh_app":
|
|
|
import json
|
|
|
cfg = json.loads(job.config_json or "{}")
|
|
|
- app_id = cfg.get("app_id", "")
|
|
|
- prefix = f"{instance}_{app_id}_"
|
|
|
+ return f"{instance_name}_{cfg.get('app_id', '')}_"
|
|
|
elif job.type == "ynh_system":
|
|
|
- prefix = f"{instance}_system_"
|
|
|
+ return f"{instance_name}_system_"
|
|
|
elif job.type in ("mysql", "postgresql"):
|
|
|
import json
|
|
|
cfg = json.loads(job.config_json or "{}")
|
|
|
- dbname = cfg.get("database", "")
|
|
|
- prefix = f"{instance}_{job.type}_{dbname}_"
|
|
|
+ return f"{instance_name}_{job.type}_{cfg.get('database', '')}_"
|
|
|
elif job.type == "custom_dir":
|
|
|
- import re
|
|
|
label = re.sub(r'[^a-z0-9]+', '-', job.name.lower().strip()).strip('-')
|
|
|
- prefix = f"{instance}_{label}_"
|
|
|
+ return f"{instance_name}_{label}_"
|
|
|
else:
|
|
|
- prefix = f"{instance}_{job.name.lower().replace(' ', '-')}_"
|
|
|
+ return f"{instance_name}_{job.name.lower().replace(' ', '-')}_"
|
|
|
|
|
|
- from jobs.utils import sudo_listdir
|
|
|
- archives = []
|
|
|
- for fname in sudo_listdir(backup_dir):
|
|
|
- if fname.startswith(prefix) and fname.endswith(".tar"):
|
|
|
- archives.append(fname)
|
|
|
|
|
|
+def _list_archives_for_job(job, backup_dir):
|
|
|
+ """Liste les archives correspondant à ce job, triées par date (plus ancienne en premier)."""
|
|
|
+ from flask import current_app
|
|
|
+ instance = current_app.config["INSTANCE_NAME"]
|
|
|
+ prefix = _job_archive_prefix(job, instance)
|
|
|
+
|
|
|
+ from jobs.utils import sudo_listdir
|
|
|
+ archives = [
|
|
|
+ fname for fname in sudo_listdir(backup_dir)
|
|
|
+ if fname.startswith(prefix) and fname.endswith(".tar")
|
|
|
+ ]
|
|
|
archives.sort(key=_extract_date)
|
|
|
return archives
|
|
|
|
|
|
|
|
|
+def apply_remote_retention(job, client):
|
|
|
+ """Applique la rétention sur l'instance distante après un push.
|
|
|
+
|
|
|
+ Filtre les archives par le même préfixe que le job local et applique
|
|
|
+ la même politique (count/daily). Ne touche pas aux archives des autres jobs.
|
|
|
+ """
|
|
|
+ from flask import current_app
|
|
|
+ instance = current_app.config["INSTANCE_NAME"]
|
|
|
+ prefix = _job_archive_prefix(job, instance)
|
|
|
+
|
|
|
+ try:
|
|
|
+ remote_archives = client.get_archives()
|
|
|
+ except Exception:
|
|
|
+ return []
|
|
|
+
|
|
|
+ matching = sorted(
|
|
|
+ [a["name"] + ".tar" for a in remote_archives if a["name"].startswith(prefix)],
|
|
|
+ key=_extract_date,
|
|
|
+ )
|
|
|
+
|
|
|
+ if job.retention_mode == "count":
|
|
|
+ to_delete = _retention_count(matching, job.retention_value)
|
|
|
+ elif job.retention_mode == "daily":
|
|
|
+ to_delete = _retention_daily(matching, job.retention_value)
|
|
|
+ else:
|
|
|
+ return []
|
|
|
+
|
|
|
+ deleted = []
|
|
|
+ for archive_filename in to_delete:
|
|
|
+ base = os.path.splitext(archive_filename)[0]
|
|
|
+ try:
|
|
|
+ client.delete_archive(base)
|
|
|
+ deleted.append(base)
|
|
|
+ except Exception:
|
|
|
+ pass
|
|
|
+ return deleted
|
|
|
+
|
|
|
+
|
|
|
def _extract_date(filename):
|
|
|
match = re.search(r'(\d{8})', filename)
|
|
|
if match:
|