From fe2a893fbffb036f9045f36eb6083b984130d332 Mon Sep 17 00:00:00 2001 From: Thomas Stallinger Date: Fri, 28 Aug 2026 11:02:58 +0200 Subject: [PATCH] Sprechender Download-Dateiname statt immer 'tuxflotte-installationsmedium.iso' Live-Fund beim Self-Service-Flow-Test: bei mehreren Bau-Durchlaeufen/ Workspaces war der Download-Dateiname nicht unterscheidbar. Jetzt zusammengesetzt aus Backend+Version+Workspace (aus der verwendeten Bereitstellungsvorlage) + Bau-Datum, z.B. 'tuxflotte-Linux-Mint-22-Entwickler-2026-08-28.iso'. Co-Authored-By: Claude Opus 5 --- routers/installationsmedium.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/routers/installationsmedium.py b/routers/installationsmedium.py index 8717468..2f3802c 100644 --- a/routers/installationsmedium.py +++ b/routers/installationsmedium.py @@ -1,3 +1,4 @@ +import re from datetime import datetime, timedelta, timezone from fastapi import APIRouter, Depends, Form, HTTPException, Request @@ -13,6 +14,18 @@ from templating import templates router = APIRouter() +def _dateikomponente(text: str) -> str: + """ + Bereinigt einen Textbaustein fuer den Einsatz in einem Download- + Dateinamen (Leerzeichen/Umlaute/Sonderzeichen -> Bindestrich) - live + gefunden: der Download hiess immer nur 'tuxflotte-installationsmedium.iso', + bei mehreren Bau-Durchlaeufen/Workspaces kaum auseinanderzuhalten. + """ + + bereinigt = re.sub(r"[^A-Za-z0-9]+", "-", text).strip("-") + return bereinigt or "unbekannt" + + def fetch_konfiguration(organization_id: str) -> dict | None: with get_database_connection() as conn: with conn.cursor() as cur: @@ -275,6 +288,23 @@ def installationsmedium_download(user=Depends(get_current_user)): if iso_build["status"] != "completed": raise HTTPException(status_code=409, detail="Das Installationsmedium ist noch nicht fertig gebaut.") + # Sprechender Dateiname statt immer desselben generischen Namens (siehe + # _dateikomponente()) - Backend+Version+Workspace aus der verwendeten + # Bereitstellungsvorlage, Datum aus dem Bau-Abschluss. + vorlagen_result = anode_request("GET", f"/api/v1/organizations/{organization_id}/bereitstellungsvorlagen") + vorlagen = vorlagen_result.get("bereitstellungsvorlagen", []) if vorlagen_result.get("success") else [] + vorlage = next((v for v in vorlagen if v["id"] == konfiguration["bereitstellungsvorlage_id"]), None) + + if vorlage: + backend_teil = _dateikomponente(f"{vorlage['backend']['name']}-{vorlage['backend']['version']}") + workspace_teil = _dateikomponente(vorlage["workspace"]["name"]) + else: + backend_teil = "unbekannt" + workspace_teil = "unbekannt" + + datum_teil = (iso_build.get("finished_at") or datetime.now(timezone.utc).isoformat())[:10] + dateiname = f"tuxflotte-{backend_teil}-{workspace_teil}-{datum_teil}.iso" + def stream_datei(): with anode_stream("GET", f"/api/v1/iso-builds/{build_id}/download") as response: response.raise_for_status() @@ -284,5 +314,5 @@ def installationsmedium_download(user=Depends(get_current_user)): return StreamingResponse( stream_datei(), media_type="application/octet-stream", - headers={"Content-Disposition": 'attachment; filename="tuxflotte-installationsmedium.iso"'}, + headers={"Content-Disposition": f'attachment; filename="{dateiname}"'}, )