Files
homelab-frontend/tasks/8.1-serviceadapter-crd-and-informer.md
T

2.9 KiB

8.1 — ServiceAdapter CRD, informer, RBAC (GREEN)

Phase: 8 — ServiceAdapter CRD rollout Stage: RED Depends on: Phase 6 (cutover) — done, confirmed live in-cluster

Design contract: API_ROUTING_HYBRID_DESIGN.md §1.

G2 note — read before objecting. G2 says "the gateway holds no Kubernetes credentials, config comes from git not a CRD." This task deliberately supersedes G2 for this one narrow purpose; the acknowledged-supersession rationale is written out in API_ROUTING_HYBRID_DESIGN.md's Context section (top of that doc) and in INDEX.md's G2 line. Do not treat this as a task-file error — the supersession is intentional and pre-approved, scoped to exactly the read-only Role this task adds.

  • apis/gateway/v1/serviceadapter_types.go defines ServiceAdapter matching the design doc's example CRs (§1, §6): spec.serviceName, spec.upstream.{url,timeoutSeconds}, spec.auth.{required,capability}, spec.retryable, spec.resources[].name, spec.resources[].methods[].{verb,upstreamPath,requestSchema,responseSchema,auth}
  • controller-gen generates the CRD YAML from those types into k8s/crd-serviceadapter.yaml, added to k8s/kustomization.yaml's resources:
  • CRD is namespace-scoped, group gateway.riotpiao.com/v1, kind ServiceAdapter — not cluster-scoped
  • k8s/rbac.yaml gains a namespace-scoped Role/RoleBinding (get, list, watch only, no status/finalizers verbs) for the existing api-gateway ServiceAccount, exactly as specced in §1
  • internal/serviceadapter/registry.go: client-go SharedInformer on ServiceAdapter in namespace api, feeding an in-memory map keyed by spec.serviceName
  • Add/Update/Delete informer callbacks mutate the map directly; no gateway restart required to pick up a CR change
  • A ServiceAdapter CR with a malformed requestSchema/responseSchema (per 8.3's DSL) logs an error and is skipped — it does not crash the informer or block other adapters from loading
  • go build ./... succeeds with the new apis/ package and internal/serviceadapter/registry.go in the tree

Verify

kubectl -n api get role api-gateway-serviceadapter-reader -o yaml
# expected: rules limited to gateway.riotpiao.com/serviceadapters, verbs [get list watch]

kubectl apply -f k8s/crd-serviceadapter.yaml --dry-run=server
# expected: no error — CRD schema itself validates

kubectl -n api apply -f - <<'EOF'
apiVersion: gateway.riotpiao.com/v1
kind: ServiceAdapter
metadata: { name: smoke-test }
spec:
  serviceName: smoke-test
  upstream: { url: http://example.invalid, timeoutSeconds: 5 }
  auth: { required: false }
  resources: []
EOF
kubectl -n api logs deploy/api-gateway --since=10s | grep -i "smoke-test"
# expected: informer logs an Add event for smoke-test within resync/watch latency, no restart
kubectl -n api delete serviceadapter smoke-test