Zum Inhalt

Polycrate API 0.15.2

Release-Datum: 19. April 2026
Typ: Fix

Highlights

  • Stabilerer Icon-ResolverGET /api/v1/backups/backup-schedules/<id>/ und andere ManagedObject-Retrieves fallen nicht mehr mit HTTP 500 aus, wenn für eine Klasse kein Icon-SVG hinterlegt ist. Der Resolver fällt auf ein Default-Icon zurück und loggt die Lücke.
  • Saubere 409-Semantik auf Create – Unique-Constraint-Verstöße (K8sCluster und andere ManagedObject-Endpoints) liefern HTTP 409 Conflict mit strukturiertem Error-Body statt HTTP 500. Voraussetzung für robustes Re-Adoption im Operator.
  • Loopback-Integration sichtbar und debugbar – Organization-Detail zeigt eine read-only Card mit loopback_org_id, loopback_project_id und Match-Status (auto-resolved / manually set / unresolved). Auto-Match-Fehler propagieren als Condition am SystemOwner.
  • Humanized Bandwidth-WerteLoadbalancerInstance Bandwidth-Tab und Organization LB-Bandwidth-Chart rendern Werte mit B/s, KB/s, MB/s, GB/s in Tooltips und Achsen-Ticks. Der Org-Chart hatte zusätzlich eine falsche Unit (bytes statt bytes/s), das ist korrigiert.
  • CatalogueApp Admin/Form entrümpelt – Das Legacy-Feld template_block ist aus Form und Admin raus, registry_url ist das einzige User-sichtbare Quellfeld.

Artefakte

Docker Image

docker pull cargo.ayedo.cloud/polycrate/polycrate-api:0.15.2

Block

polycrate pull cargo.ayedo.cloud/ayedo/k8s/polycrate-api
polycrate run polycrate-api install

Hintergrund

Nach dem 0.15.0-Release (Bundled Feature Release mit User/Contact-Migration, Keycloak-Integration, Artifacts→Blocks, externe DNS via Lexicon, RBAC und Managed Object Dashboard) sind während des Operator-Rollouts auf 0.15.1 mehrere eng umrissene Regressionen und UX-Schwachstellen sichtbar geworden. 0.15.2 sammelt die Fixes in einem Hotfix-Release ohne Breaking-Changes und ohne Schema-Migration.

Fixes

Fix 1: Icon-Resolver robust machen

Problem: GET /api/v1/backups/backup-schedules/<id>/ schlug mit HTTP 500 fehl, weil kein backupschedule.svg unter polycrate_api/img/object_icons/ existierte und der Resolver die ValueError aus static() nicht abfing.

Lösung:

  • Neues Icon src/static/polycrate_api/img/object_icons/backupschedule.svg hinzugefügt.
  • resolve_managed_object_icon_url in src/polycrate_api/serializers/common.py fängt jetzt fehlende Assets ab (staticfiles_storage.exists / ValueError) und fällt auf ein Default-Icon zurück. Die fehlende Datei wird geloggt, damit Lücken in der Icon-Abdeckung erkennbar bleiben.
  • Audit aller ManagedObject-Subklassen auf verfügbare Icons; vorhandene Lücken in der selben Änderung geschlossen.

Fix 2: 409 Conflict bei Unique-Constraint statt 500

Problem: POST /api/v1/kubernetes/clusters/ (und analog andere ManagedObject-Create-Endpoints) lieferte bei Unique-Constraint-Verstößen HTTP 500, weil IntegrityError ungefangen bis zum DRF-Handler durchschlug. Für den Operator-Reconciler sah jeder "existiert bereits"-Fall damit aus wie ein echter Server-Fehler und wurde mit exponentiellem Backoff reprobiert statt per Lookup adoptiert.

Lösung:

  • ManagedObjectBaseViewset.create() fängt IntegrityError und mappt Unique-Constraint-Verstöße auf HTTP 409 mit strukturiertem Body:
{"detail": "K8sCluster with this name already exists in this workspace", "code": "duplicate"}
  • Gilt automatisch für alle ManagedObject-Subklassen, nicht nur K8sCluster. Kein Per-Viewset-Patch nötig.
  • Der operator-seitige Lookup-Retry über alle Reconciler hinweg ist in polycrate-cli Spec 154 beschrieben und folgt in einem separaten CLI-Release. Er ist für den Rollout von 0.15.2 nicht blockierend — das API-Verhalten ist für sich genommen korrekt und rückwärtskompatibel.

Fix 3: CatalogueAppForm/Admin von template_block bereinigen

Problem: Nach der Migration von template_block zu registry_url (0.15.0 Artifacts→Blocks Refactoring) referenzierten CatalogueAppForm.Meta.fields und CatalogueAppAdmin noch das alte Feld. Das führte zu Django-SystemCheck-Warnings (fields.E*) und in bestimmten Admin-Pfaden zu Rendering-Fehlern.

Lösung:

  • template_block entfernt aus src/artifacts/forms.py::CatalogueAppForm.Meta.fields und aus src/artifacts/admin.py::CatalogueAppAdmin (list_display, list_filter, search_fields, raw_id_fields, fieldsets, readonly_fields).
  • registry_url in Form und Admin sichtbar gemacht (list_display, search_fields).
  • Repo-weiter Audit via rg -n "template_block" src/ — verbleibende Treffer nur noch in historischen Migrations (0047_catalogueapp_registry_url, 0048_*).
  • Client-Artefakte (schemas.gen.js, services.gen.js) via polycrate run openapi generate neu gebaut.

Fix 4: Loopback-Integration — Sichtbarkeit und Condition-Pfad

Problem: Die Loopback-Auto-Resolve-Logik aus 0.15.0 lief zwar produktiv, war aber in der UI unsichtbar und bei Auto-Match-Failure schwer zu debuggen. Docstring und Release-Doku beschrieben zusätzlich ein veraltetes Matching-Verhalten ("match by slug ayedo"), was nicht mehr dem Code entsprach.

Lösung (Default bleibt Auto-Resolve, keine manuelle Pflege nötig):

  • Dashboard-Card auf Organization-Detail (nur wenn LOOPBACK_INTEGRATION_ENABLED=true):
  • Zeigt loopback_org_id (auf dem SystemOwner relevant) und loopback_project_id read-only mit Copy-Button.
  • Match-Status-Badge: auto-resolved, manually set, unresolved (auto-match failed), not set.
  • Keine Write-Komponente in der UI — Editieren nur über Django-Admin.
  • Condition-Propagation in Organization._reconcile_loopback_clusters:
  • Fehlender Org-Match auf SystemOwner → Condition mit type=LoopbackOrgResolved, status=False, reason=NoNameMatch, Message inkl. erwartetem legal_name.
  • Fehlender Project-Match nur dann als Condition, wenn für die Org ein Match erwartet wird. Orgs ohne Loopback-Präsenz erzeugen kein Dauer-Warning.
  • Bei erfolgreichem Resolve: Condition.status=True bzw. Condition wird entfernt.
  • Client-Robustheit: LoopbackClient klassifiziert 401/403 als eigene Exception mit Hinweis auf LOOPBACK_API_KEY, damit Condition-Messages aussagekräftig bleiben.
  • Docstring/Doku aktualisiert: Matching-Regeln explizit (Loopback.org.name == SystemOwner.legal_name, Loopback.project.name == Polycrate.org.slug). Der zugehörige Abschnitt in den 0.15.0-Release-Notes wurde ergänzt.

Fix 5: LoadbalancerInstance-Bandwidth humanizen

Problem: Der Bandwidth-Tab auf LoadbalancerInstance zeigte rohe Bytes-pro-Sekunde-Werte in Tooltips und Ticks (1180000 statt 1.18 MB/s).

Lösung: Frontend-Only-Fix in src/static/polycrate_api/js/metric-chart.js. Ein neuer formatBytesPerSecond-Helper skaliert pro Wert automatisch auf B/s, KB/s, MB/s oder GB/s. Negative Werte bekommen ein --Präfix, 0 bleibt 0 B/s. Keine Änderung an Prometheus-Queries oder Metric-Semantik.

Fix 6: Organization LB Bandwidth Chart — Unit korrigieren

Problem: Das lb_bandwidth-Chart auf der Organization-Detail-Seite deklarierte im API-Response "unit": "bytes" statt "bytes/s". Die gelieferten Werte waren korrekt (polycrate_io_api_loadbalancer_traffic_bytes_per_second), aber das Frontend formatierte sie als kumulativen Byte-Wert ohne /s-Suffix.

Lösung: Backend-Only-Fix in src/organizations/models.py: chart_spec.unit für lb_bandwidth auf bytes/s korrigiert. Damit rendert der Org-Chart konsistent mit dem Instance-Chart (Fix 5). Keine Änderung an _metric_lb_bandwidth oder an der Prometheus-Query.

Kompatibilität

  • Kein Breaking-Change, keine Schema-Migration.
  • 409-Semantik auf Create-Endpoints ist eine Korrektur des dokumentierten Verhaltens; Clients, die bisher 500 als Duplikat-Signal interpretiert haben, müssen nachziehen (der Operator-Fix dafür ist in polycrate-cli Spec 154 getrackt und nicht blockierend für diesen Release).
  • Alle Icon-/Chart-/Loopback-Änderungen sind additiv und rückwärtskompatibel.

Nach dem Deployment

  • Optional: Condition-Liste auf der SystemOwner-Organization prüfen. Steht dort LoopbackOrgResolved=False mit reason=NoNameMatch, stimmt entweder legal_name nicht mit der Loopback-Org überein, oder LOOPBACK_INTEGRATION_ENABLED ist fälschlich aktiv. Fix via Django-Admin (loopback_org_id setzen) oder via Env-Var.
  • Prüfen, dass der Bandwidth-Tab der Organization-Detail-Seite Werte jetzt mit /s-Suffix rendert und dass LoadbalancerInstance-Bandwidth-Tooltips humanisiert sind.