Compare commits
2 Commits
fd5f12a8ca
...
8000f76457
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8000f76457 | ||
|
|
c45a6a0561 |
@@ -33,7 +33,7 @@ class Mittwald:
|
||||
|
||||
@staticmethod
|
||||
def _real_http(method, url, headers, body):
|
||||
r = httpx.request(method, url, headers=headers, json=body, timeout=60)
|
||||
r = httpx.request(method, url, headers=headers, json=body, timeout=60, follow_redirects=True) # wie `requests` im alten deploy.py
|
||||
try:
|
||||
data = r.json() if r.content else None
|
||||
except ValueError:
|
||||
@@ -56,7 +56,7 @@ class Mittwald:
|
||||
raise DryRunSkip()
|
||||
raise DeployError("MITTWALD_API_TOKEN nicht gesetzt.")
|
||||
status, data, text = self._http(method, f"{self.base}{path}", {"Authorization": f"Bearer {self.token}", "Content-Type": "application/json"}, body)
|
||||
if status >= 400:
|
||||
if status >= 300: # 3xx (nicht gefolgte Weiterleitung) darf nie als Erfolg mit leerem Body durchgehen
|
||||
msg = f"{method} {path} → HTTP {status}: {text}"
|
||||
if fatal:
|
||||
raise DeployError(msg)
|
||||
|
||||
@@ -62,7 +62,7 @@ class OnyvaLogin:
|
||||
|
||||
@staticmethod
|
||||
def _real(method, url, headers, body):
|
||||
r = httpx.request(method, url, headers=headers, json=body, timeout=30)
|
||||
r = httpx.request(method, url, headers=headers, json=body, timeout=30, follow_redirects=True)
|
||||
try:
|
||||
data = r.json() if r.content else None
|
||||
except ValueError:
|
||||
|
||||
@@ -80,8 +80,11 @@ def run(tenant_id: str, *, mw_http=None, oidc_client=None, self_get=None) -> dic
|
||||
# Secrets / OIDC / STT
|
||||
will_create = oc["mode"] == "managed" and onyva_login.key_present() and not has_oidc_secrets
|
||||
real_missing = [m for m in missing if not (will_create and m in ("OIDC_CLIENT_ID", "OIDC_CLIENT_SECRET"))]
|
||||
hint = "Tenant → Secrets (tenantspezifisch) bzw. Einstellungen → Geteilte Secrets (z. B. CORTECS_API_KEY)."
|
||||
if draft:
|
||||
hint += " Geprüft wird der VERÖFFENTLICHTE Stand – Änderungen im Entwurf (z. B. STT-Provider) erst veröffentlichen."
|
||||
add("secrets", "ok" if not real_missing else "fail", "Pflicht-Secrets", "vollständig" if not real_missing else "fehlen: " + ", ".join(real_missing),
|
||||
"" if not real_missing else "Tenant → Secrets (tenantspezifisch) bzw. Einstellungen → Geteilte Secrets (z. B. CORTECS_API_KEY).")
|
||||
"" if not real_missing else hint)
|
||||
if will_create:
|
||||
add("oidcnew", "info", "OIDC-Client", "wird beim Deploy automatisch im Login angelegt (Client-ID/-Secret sofort gespeichert)")
|
||||
elif oc["mode"] != "off" and not onyva_login.key_present():
|
||||
@@ -92,7 +95,7 @@ def run(tenant_id: str, *, mw_http=None, oidc_client=None, self_get=None) -> dic
|
||||
add("members", "warn", "Freigaben", "auth_mode „required“, aber keine Nutzer gepflegt – niemand kann sich anmelden",
|
||||
"Domain & Login → Freigaben: mindestens dich eintragen (Nutzer muss im Login existieren).")
|
||||
if stt_provider != "cortecs":
|
||||
add("stt", "info", "STT-Provider", stt_provider + " – braucht MISTRAL_API_KEY")
|
||||
add("stt", "info", "STT-Provider (veröffentlichter Stand)", stt_provider + " – braucht MISTRAL_API_KEY" + (" · im Entwurf evtl. schon geändert, aber noch nicht veröffentlicht" if draft else ""))
|
||||
# Inhalt
|
||||
with session() as db:
|
||||
t = db.get(Tenant, tenant_id)
|
||||
|
||||
@@ -492,3 +492,22 @@ def test_cortecs_key_from_admin_env_counts_as_set_and_reaches_the_container(clie
|
||||
assert deploy.build_env(db, t, reveal=True)["CORTECS_API_KEY"] == "ck-aus-env"
|
||||
assert "ck-aus-env" not in str(deploy.build_env(db, t, reveal=False))
|
||||
assert "aus Admin-Env" in deploy.build_env(db, t, reveal=False)["CORTECS_API_KEY"]
|
||||
|
||||
|
||||
def test_http_clients_follow_redirects_and_3xx_is_never_success(monkeypatch):
|
||||
import httpx
|
||||
from app.services import mittwald as mwmod, onyva_login
|
||||
from app.services.mittwald import DeployError, Mittwald
|
||||
seen = []
|
||||
|
||||
class R:
|
||||
status_code, content, text = 200, b"[]", "[]"
|
||||
def json(self): return []
|
||||
|
||||
monkeypatch.setattr(httpx, "request", lambda *a, **k: (seen.append(k), R())[1])
|
||||
Mittwald._real_http("GET", "https://x/v2/stacks/", {}, None)
|
||||
onyva_login.OnyvaLogin._real("GET", "https://x/api/v1/apps", {}, None)
|
||||
assert all(k.get("follow_redirects") is True for k in seen) and len(seen) == 2
|
||||
# Eine nicht gefolgte 308-Weiterleitung (leerer Body) ist ein Fehler, kein „null“
|
||||
with pytest.raises(DeployError, match="308"):
|
||||
Mittwald("t", "https://api.test/v2", False, lambda m: None, lambda *a: (308, None, "")).api("GET", "/projects/p/stacks/", write=False)
|
||||
|
||||
Reference in New Issue
Block a user