mirror of
https://github.com/sredevopsorg/deepseek-kubernetes-sandbox.git
synced 2026-11-03 01:13:24 +00:00
Handshake under the pod-IP authority for WebSocket upgrades (#11)
DSH binds its auth cookie to the request authority (payload.authority === authority) and looks the cookie up under a name derived from the Host. The upgrade presents Host = pod-IP:3080 (websockets derives it from the URI), so a cookie minted for the browser authority is rejected with 401. The previous pod-IP change fixed the Host fence (403) but not this, so the client kept looping on "[connection] connection lost, retry #N". Perform the WS handshake under the pod-IP authority too, so the cookie matches the Host the upgrade carries. The HTTP path keeps the browser authority. Also serialise the lazy Kubernetes client init: anyio.to_thread can enter it concurrently, and a thread that observes _crd set while _core is still None returns a None client. The live log showed the result: AttributeError: 'NoneType' object has no attribute 'read_namespaced_pod' Co-authored-by: SREDevOpsAgents <agents@sredevops.org>
This commit is contained in:
committed by
GitHub
parent
abe5b4d5bb
commit
0a61e57db4
@@ -10,6 +10,7 @@ use Starlette's ``TestClient`` (which runs the lifespan) against a fake
|
||||
import asyncio
|
||||
import hashlib
|
||||
import json
|
||||
import threading
|
||||
import time
|
||||
from types import SimpleNamespace
|
||||
|
||||
@@ -529,6 +530,42 @@ async def test_kubernetes_get_pod_normalises_the_v1pod_model(monkeypatch):
|
||||
assert pod["metadata"]["uid"] == "pod-uid-9"
|
||||
|
||||
|
||||
def test_kubernetes_clients_initialise_once_under_concurrency(monkeypatch):
|
||||
"""_call runs on a worker pool: the lazy init must not hand out a None client."""
|
||||
import gateway as gw
|
||||
from gateway import Kubernetes
|
||||
|
||||
created = []
|
||||
|
||||
class Crd:
|
||||
def __init__(self):
|
||||
created.append("crd")
|
||||
|
||||
class SlowCore:
|
||||
def __init__(self):
|
||||
time.sleep(0.05) # widen the window between _crd and _core
|
||||
created.append("core")
|
||||
|
||||
monkeypatch.setattr(gw.k8s_client, "CustomObjectsApi", Crd)
|
||||
monkeypatch.setattr(gw.k8s_client, "CoreV1Api", SlowCore)
|
||||
monkeypatch.setattr(gw.k8s_config, "load_incluster_config", lambda: None)
|
||||
|
||||
k8s = Kubernetes("test-ns")
|
||||
results = []
|
||||
|
||||
def worker():
|
||||
results.append(k8s._clients())
|
||||
|
||||
threads = [threading.Thread(target=worker) for _ in range(8)]
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
|
||||
assert all(core is not None for _, core in results)
|
||||
assert created.count("core") == 1
|
||||
|
||||
|
||||
# --- health / landing / redirect ------------------------------------------
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user