mirror of
https://github.com/sredevopsorg/deepseek-kubernetes-sandbox.git
synced 2026-11-03 01:13:24 +00:00
Normalise the pod model returned by CoreV1Api (#7)
get_pod() returned kubernetes' V1Pod model, but dsh_cookie() indexes it as a
dict (pod.get("metadata")), so every gateway handshake crashed with:
AttributeError: 'V1Pod' object has no attribute 'get'
and every proxied request answered 500. The unit tests inject a fake that
returns dicts, so the mismatch only appeared against a real API server.
Normalise at the adapter boundary with ApiClient().sanitize_for_serialization
and cover it with a test that returns a real V1Pod.
Also document digest-pinned gateway rollouts: the workflow publishes the
mutable :gateway tag, and imagePullPolicy: IfNotPresent keeps the cached old
image across kubectl apply / rollout restart.
Co-authored-by: SREDevOpsAgents <agents@sredevops.org>
This commit is contained in:
committed by
GitHub
parent
c193ed21a4
commit
9dea4a7f67
@@ -198,6 +198,18 @@ kubectl -n dsh-demo port-forward svc/dsh-gateway 18080:8080
|
|||||||
|
|
||||||
> The gateway binds `8080`; the local port-forward uses `18080` and never `3080`.
|
> The gateway binds `8080`; the local port-forward uses `18080` and never `3080`.
|
||||||
>
|
>
|
||||||
|
> **Re-deploying after a new image?** The workflow publishes the mutable `:gateway` tag and the
|
||||||
|
> Deployment uses `imagePullPolicy: IfNotPresent`, so a node that already cached the tag keeps
|
||||||
|
> the old image across `kubectl apply`/`rollout restart`. Pin the digest for a reproducible
|
||||||
|
> rollout (the workflow's `Inspect image` step and `docker buildx imagetools inspect` both show
|
||||||
|
> it):
|
||||||
|
>
|
||||||
|
> ```bash
|
||||||
|
> kubectl -n dsh-demo set image deploy/dsh-gateway \
|
||||||
|
> gateway=ghcr.io/sredevopsorg/deepseek-kubernetes-sandbox@sha256:<digest>
|
||||||
|
> kubectl -n dsh-demo rollout status deploy/dsh-gateway --timeout=120s
|
||||||
|
> ```
|
||||||
|
>
|
||||||
> **Applying over an existing install?** Run `kubectl diff -f 10-sandboxtemplate.yaml`
|
> **Applying over an existing install?** Run `kubectl diff -f 10-sandboxtemplate.yaml`
|
||||||
> first. Cluster-specific fields such as `nodeAffinity` and the warm-pool replica count are
|
> first. Cluster-specific fields such as `nodeAffinity` and the warm-pool replica count are
|
||||||
> intentionally not in the repo manifests; preserve them with a targeted patch instead of a
|
> intentionally not in the repo manifests; preserve them with a targeted patch instead of a
|
||||||
|
|||||||
@@ -475,13 +475,17 @@ class Kubernetes:
|
|||||||
|
|
||||||
async def get_pod(self, name: str) -> dict | None:
|
async def get_pod(self, name: str) -> dict | None:
|
||||||
try:
|
try:
|
||||||
return await self._call(
|
pod = await self._call(
|
||||||
"core", "read_namespaced_pod", name, self.namespace
|
"core", "read_namespaced_pod", name, self.namespace
|
||||||
)
|
)
|
||||||
except ApiException as exc:
|
except ApiException as exc:
|
||||||
if exc.status == 404:
|
if exc.status == 404:
|
||||||
return None
|
return None
|
||||||
raise
|
raise
|
||||||
|
# CoreV1Api returns a V1Pod model while every other call in this module
|
||||||
|
# (CRD calls, fakes in tests) yields a dict. Normalise at the boundary
|
||||||
|
# so callers can keep using ``pod.get(...)``.
|
||||||
|
return k8s_client.ApiClient().sanitize_for_serialization(pod)
|
||||||
|
|
||||||
async def read_pod_logs(
|
async def read_pod_logs(
|
||||||
self, name: str, container: str, tail_lines: int
|
self, name: str, container: str, tail_lines: int
|
||||||
|
|||||||
@@ -497,6 +497,25 @@ async def test_kubernetes_read_pod_logs_forwards_container_and_tail(monkeypatch)
|
|||||||
assert calls == [(("pod-1", "test-ns"), {"container": "dsh-web", "tail_lines": 200})]
|
assert calls == [(("pod-1", "test-ns"), {"container": "dsh-web", "tail_lines": 200})]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_kubernetes_get_pod_normalises_the_v1pod_model(monkeypatch):
|
||||||
|
"""CoreV1Api returns a V1Pod model; callers index it like a dict."""
|
||||||
|
from kubernetes.client import V1ObjectMeta, V1Pod
|
||||||
|
|
||||||
|
from gateway import Kubernetes
|
||||||
|
|
||||||
|
async def fake_call(which, method, *args):
|
||||||
|
return V1Pod(metadata=V1ObjectMeta(name="dsh-alice", uid="pod-uid-9"))
|
||||||
|
|
||||||
|
k8s = Kubernetes("test-ns")
|
||||||
|
monkeypatch.setattr(k8s, "_call", fake_call)
|
||||||
|
|
||||||
|
pod = await k8s.get_pod("dsh-alice")
|
||||||
|
|
||||||
|
assert isinstance(pod, dict)
|
||||||
|
assert pod["metadata"]["uid"] == "pod-uid-9"
|
||||||
|
|
||||||
|
|
||||||
# --- health / landing / redirect ------------------------------------------
|
# --- health / landing / redirect ------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user