diff --git a/platform/app.py b/platform/app.py index 39a5330..9e29106 100644 --- a/platform/app.py +++ b/platform/app.py @@ -70,11 +70,11 @@ def _stream_restore(job_id, cmd): restore_jobs[job_id]['status'] = 'error' -def _stream_backup(job_id, script_path): +def _stream_backup(job_id, script_path, extra_args=None): backup_jobs[job_id] = {'status': 'running', 'log': [], 'started': time.time()} try: proc = subprocess.Popen( - ['bash', script_path], + ['bash', script_path] + (extra_args or []), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1 ) @@ -442,8 +442,21 @@ def api_backup_run(): 'message': f'Backup script not found at {script}' }), 500 + # Optional {"apps": [...]} body — omitted, empty, or "all apps checked" + # all mean the same thing as before this existed: no --apps flag, every + # app bundled into one archive together (the script's own default). + # Only becomes --apps a,b when the UI's app-picker has SOME apps + # unchecked, for a deliberate one-off single/partial-app backup. + data = request.get_json(silent=True) or {} + raw_apps = data.get('apps', []) + selected = sorted({ + a.strip().lower() for a in raw_apps + if isinstance(a, str) and a.strip().lower() in ALLOWED_RESTORE_APPS + }) + extra_args = ['--apps', ','.join(selected)] if selected and len(selected) < len(ALLOWED_RESTORE_APPS) else [] + job_id = str(uuid.uuid4()) - t = threading.Thread(target=_stream_backup, args=(job_id, script), daemon=True) + t = threading.Thread(target=_stream_backup, args=(job_id, script, extra_args), daemon=True) t.start() return jsonify({'success': True, 'job_id': job_id, 'status': 'started'}) diff --git a/platform/static/js/platform.js b/platform/static/js/platform.js index 63a6db0..7adb33f 100644 --- a/platform/static/js/platform.js +++ b/platform/static/js/platform.js @@ -410,11 +410,15 @@ function renderBackupList(items, id, source) { const detailsBtn = typeof showBackupDetails === 'function' ? `` : ''; + const appsLabel = (b.apps && b.apps.length) + ? `${b.apps.length >= 5 ? 'All apps' : escapeHtml(b.apps.join(', '))}` + : ''; return `
Manually trigger a backup of all containers
++ All apps are backed up together into one archive by default. Uncheck any app to leave it out — + useful for a quick one-off backup of a single app before a risky change, without waiting on the rest. +
+