51 lines
2.9 KiB
Markdown
51 lines
2.9 KiB
Markdown
# 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](../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
|
||
|
|
|
||
|
|
```bash
|
||
|
|
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
|
||
|
|
```
|