diff --git a/apps/api/tests/test_ollama_prod_manifest_order.py b/apps/api/tests/test_ollama_prod_manifest_order.py new file mode 100644 index 00000000..4fea9160 --- /dev/null +++ b/apps/api/tests/test_ollama_prod_manifest_order.py @@ -0,0 +1,37 @@ +from __future__ import annotations + +from pathlib import Path + +import yaml + + +ROOT = Path(__file__).resolve().parents[3] +EXPECTED_ORDER = { + "OLLAMA_URL": "http://192.168.0.110:11435", + "OLLAMA_SECONDARY_URL": "http://192.168.0.110:11436", + "OLLAMA_FALLBACK_URL": "http://192.168.0.110:11437", +} + + +def _load_single_doc(path: Path) -> dict: + docs = [doc for doc in yaml.safe_load_all(path.read_text()) if doc] + assert docs, f"no YAML documents in {path}" + return docs[0] + + +def test_prod_configmap_preserves_ollama_policy_order() -> None: + configmap = _load_single_doc(ROOT / "k8s/awoooi-prod/04-configmap.yaml") + + assert configmap["data"] | EXPECTED_ORDER == configmap["data"] + assert {configmap["data"][key] for key in EXPECTED_ORDER} == set(EXPECTED_ORDER.values()) + + +def test_prod_deployment_preserves_ollama_policy_order() -> None: + deployment = _load_single_doc(ROOT / "k8s/awoooi-prod/06-deployment-api.yaml") + env = { + item["name"]: item.get("value") + for item in deployment["spec"]["template"]["spec"]["containers"][0]["env"] + } + + assert {key: env[key] for key in EXPECTED_ORDER} == EXPECTED_ORDER + assert {env[key] for key in EXPECTED_ORDER} == set(EXPECTED_ORDER.values()) diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index ab69b893..242b8b09 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,26 @@ +## 2026-05-25|T174 Ollama manifest policy-order guard + +**背景**: + +- T173 推出 health/route cooldown 後,另一個 hotfix `fe3f1e39` 把 production manifest 改成 `11436 -> 11437 -> 11437`。 +- live route API 因此把 `11436` 顯示成 `ollama_gcp_a`,造成「label 看起來是 GCP-A,實際跑 GCP-B」的 operator 誤導。 +- 統帥已明確要求所有 Ollama 使用順序必須維持 `GCP-A -> GCP-B -> 111 -> Gemini`;GCP-A 紅燈要被顯示並 fail over,不可直接改名或跳過。 + +**本次修補**: + +- 恢復 `k8s/awoooi-prod/04-configmap.yaml` 與 `06-deployment-api.yaml`: + - `OLLAMA_URL=http://192.168.0.110:11435` + - `OLLAMA_SECONDARY_URL=http://192.168.0.110:11436` + - `OLLAMA_FALLBACK_URL=http://192.168.0.110:11437` +- 新增 `test_ollama_prod_manifest_order.py`,把 production manifest 的 Ollama policy order 鎖成測試,避免再出現 `ollama_gcp_a` label 指到 GCP-B/111。 + +**注意**: + +- 這不是否認 GCP-B 可用;正確流程是 policy 先顯示 GCP-A red,再由 failover manager 選 GCP-B 或 111。 +- 若要暫時跳過 GCP-A,必須另有「degraded lane override」欄位與前端明確標示,不能改 `OLLAMA_URL` 語意。 + +--- + ## 2026-05-25|T173 GCP upstream 紅燈驗證與 Ollama endpoint cooldown 降噪 **背景**: diff --git a/k8s/awoooi-prod/04-configmap.yaml b/k8s/awoooi-prod/04-configmap.yaml index 8462193f..8a35d2ea 100644 --- a/k8s/awoooi-prod/04-configmap.yaml +++ b/k8s/awoooi-prod/04-configmap.yaml @@ -20,8 +20,8 @@ data: # 2026-05-25 Codex: keep ADR-110 production policy visible and ordered. # High-volume callers use short endpoint cooldowns when GCP-A/B are down, # but health/status must still show GCP-A -> GCP-B -> 111 before Gemini. - OLLAMA_URL: "http://192.168.0.110:11436" - OLLAMA_SECONDARY_URL: "http://192.168.0.110:11437" + OLLAMA_URL: "http://192.168.0.110:11435" + OLLAMA_SECONDARY_URL: "http://192.168.0.110:11436" OLLAMA_FALLBACK_URL: "http://192.168.0.110:11437" OPENCLAW_URL: "http://192.168.0.188:8088" KALI_SCANNER_URL: "http://192.168.0.112:8080" diff --git a/k8s/awoooi-prod/06-deployment-api.yaml b/k8s/awoooi-prod/06-deployment-api.yaml index cf0b66c0..3f6bf4a9 100644 --- a/k8s/awoooi-prod/06-deployment-api.yaml +++ b/k8s/awoooi-prod/06-deployment-api.yaml @@ -70,9 +70,9 @@ spec: - name: TELEGRAM_ENABLE_POLLING value: "true" - name: OLLAMA_URL - value: "http://192.168.0.110:11436" # 2026-05-25 Codex: GCP-B via 110 proxy; GCP-A is still offline + value: "http://192.168.0.110:11435" # 2026-05-25 Codex: GCP-A via 110 proxy; health cooldown protects noisy offline probes - name: OLLAMA_SECONDARY_URL - value: "http://192.168.0.110:11437" # 2026-05-25 Codex: local 111 via 110 proxy while GCP-A is still offline + value: "http://192.168.0.110:11436" # 2026-05-25 Codex: GCP-B via 110 proxy; fallback only after GCP-A is unavailable - name: OLLAMA_FALLBACK_URL value: "http://192.168.0.110:11437" # 2026-05-25 Codex: 111 via 110 proxy before Gemini - name: ALERT_AI_ALLOW_CLOUD_FALLBACK