1
0
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:
SREDevOps.org Agent
2026-10-21 15:29:22 -03:00
committed by GitHub
parent abe5b4d5bb
commit 0a61e57db4
3 changed files with 71 additions and 20 deletions

View File

@@ -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 ------------------------------------------