diff --git a/apps/api/src/services/resource_resolver.py b/apps/api/src/services/resource_resolver.py index d46349408..c4debe784 100644 --- a/apps/api/src/services/resource_resolver.py +++ b/apps/api/src/services/resource_resolver.py @@ -11,16 +11,17 @@ Resource Resolver - ADR-016 K8s 資源動態驗證 3. 模糊匹配 namespace 內的 Deployments 4. 回傳匹配結果或候選列表 -版本: v1.0 +版本: v1.1 建立: 2026-03-26 (台北時區) 建立者: Claude Code (首席架構師) +修改: 2026-03-26 (台北) - 新增 IResourceResolver Protocol (P2 架構改進) @see docs/adr/ADR-016-k8s-resource-naming.md """ from dataclasses import dataclass, field from difflib import SequenceMatcher -from typing import Any +from typing import Protocol, runtime_checkable import structlog @@ -64,7 +65,34 @@ class K8sResource: # ============================================================================= -# Resource Resolver +# Protocol Interface (Phase 17 P2 - 架構審查) +# ============================================================================= + +@runtime_checkable +class IResourceResolver(Protocol): + """ + ResourceResolver 介面定義 + + 用途: + - 依賴注入 (DI) 時的型別約束 + - 測試時 Mock 的型別檢查 + - 符合 leWOOOgo 積木化規範 + + @see feedback_resource_resolver_di.md + """ + + async def resolve( + self, + raw_resource: str, + namespace: str = "awoooi-prod", + resource_kind: str = "deployment", + ) -> ResolveResult: + """解析原始資源名稱為有效的 K8s 資源""" + ... + + +# ============================================================================= +# Resource Resolver Implementation # ============================================================================= class ResourceResolver: @@ -405,15 +433,45 @@ class ResourceResolver: # ============================================================================= -# Singleton Instance +# Dependency Injection Support (Phase 17 P2 改進) # ============================================================================= -_resolver: ResourceResolver | None = None +_resolver: IResourceResolver | None = None -def get_resource_resolver() -> ResourceResolver: - """取得 ResourceResolver 單例""" +def get_resource_resolver() -> IResourceResolver: + """ + 取得 ResourceResolver 實例 + + 支援兩種模式: + 1. 預設: 使用內部 singleton (向後相容) + 2. DI: 透過 set_resource_resolver() 注入自訂實例 + + 測試時可使用 set_resource_resolver(mock_resolver) 注入 mock + + Returns: + IResourceResolver: 實作 IResourceResolver Protocol 的實例 + """ global _resolver if _resolver is None: _resolver = ResourceResolver() return _resolver + + +def set_resource_resolver(resolver: IResourceResolver | None) -> None: + """ + 注入 ResourceResolver 實例 (用於 DI 或測試) + + Args: + resolver: 自訂 ResourceResolver 實例,None 則重置為預設 + + Example: + # 測試時注入 mock + mock_resolver = MockResourceResolver() + set_resource_resolver(mock_resolver) + + # 測試後重置 + set_resource_resolver(None) + """ + global _resolver + _resolver = resolver