Remove or implement unwired APIGateway CRD spec fields
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 71
- Forks
- 111
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 110
Description
Description
The APIGateway CRD (gateway.api-platform.wso2.com/v1) defines several typed spec fields that the API server accepts but the operator's reconcile/deploy path silently ignores, so setting them has no effect on the deployed gateway. The only field that actually configures the gateway today is spec.configRef (a ConfigMap of Helm values deep-merged over the operator default). This is a confusing false affordance — e.g. a user sets spec.infrastructure.image or spec.infrastructure.replicas and nothing changes.
Root cause: buildCRValuesOverlay (kubernetes/gateway-operator/internal/controller/apigateway_controller.go:757-779), the only function that turns spec.infrastructure into Helm values, reads only infra.Labels and infra.Annotations. Nothing reads infra.Image/RouterImage/Replicas/Resources/NodeSelector/Tolerations/Affinity, spec.storage, or spec.controlPlane.tls/tokenSecretRef. spec.controlPlane.host is only recorded in the operator's in-memory registry (registerGatewayInRegistry), never applied to the deployed gateway.
What is wired vs not (APIGateway CRD path):
| Field | Status |
|---|---|
spec.apiSelector |
✅ implemented (required) |
spec.configRef |
✅ implemented (the real config surface) |
spec.infrastructure.labels / annotations |
✅ implemented (→ commonLabels/commonAnnotations) |
spec.controlPlane.host |
⚠️ recorded in operator registry only, not deployed |
spec.controlPlane.tls / tokenSecretRef |
❌ ignored |
spec.infrastructure.image / routerImage |
❌ ignored |
spec.infrastructure.replicas / resources |
❌ ignored |
spec.infrastructure.nodeSelector / tolerations / affinity |
❌ ignored |
spec.storage.* |
❌ ignored |
Sample CR showing the gap:
apiVersion: gateway.api-platform.wso2.com/v1
kind: APIGateway
metadata:
name: sample-gw
namespace: sample-gw
spec:
apiSelector: # ✅ implemented (required)
scope: Namespaced
configRef: # ✅ implemented — the real config surface
name: sample-gw-values
infrastructure:
labels: { team: platform } # ✅ implemented → commonLabels
annotations: # ✅ implemented → commonAnnotations
prometheus.io/scrape: "true"
image: ghcr.io/wso2/api-platform/gateway-controller:1.2.0 # ❌ ignored
routerImage: ghcr.io/wso2/api-platform/gateway-runtime:1.2.0 # ❌ ignored
replicas: 3 # ❌ ignored
resources: # ❌ ignored
requests: { cpu: "500m", memory: 1Gi }
nodeSelector: { disktype: ssd } # ❌ ignored
tolerations: [] # ❌ ignored
affinity: {} # ❌ ignored
controlPlane:
host: "cp.example.svc.cluster.local:8443" # ⚠️ registry-only, not deployed
tls: { enabled: true } # ❌ ignored
tokenSecretRef: { name: cp-token, key: token } # ❌ ignored
storage:
type: sqlite # ❌ ignored
Where each ignored field must be set today (via spec.configRef values.yaml):
| CRD field (ignored) | Equivalent configRef key |
|---|---|
infrastructure.image |
gateway.controller.image.{repository,tag,pullPolicy} |
infrastructure.routerImage |
gateway.gatewayRuntime.image.{repository,tag,pullPolicy} |
infrastructure.replicas |
gateway.controller.deployment.replicaCount (+ gatewayRuntime) |
infrastructure.resources |
gateway.controller.deployment.resources (+ gatewayRuntime) |
infrastructure.nodeSelector/tolerations/affinity |
gateway.controller.deployment.{nodeSelector,tolerations,affinity} (+ gatewayRuntime) |
storage.type |
gateway.config.controller.storage.type |
controlPlane.host/token |
gateway.controller.controlPlane.{host,token} |
spec.configRef is a superset — most of these are already settable there.
Every ignored field in the table above already has a configRef equivalent, so configRef fully covers them today, which makes the typed infrastructure.* / storage fields effectively redundant duplication of the chart's values surface. Two exceptions:
spec.controlPlane.tlsmaps to nothing in the gateway chart — control-plane TLS is implied by thehostauthority (HTTPS/WSS scheme + port); the chart'scontroller.controlPlaneblock has onlyhost+token. This field has no backing at all and should simply be removed.spec.apiSelectoris operator-level API-selection logic, not a chart value — and it is already implemented.
Proposed resolution — pick one surface, don't leave both half-wired:
Option A — Implement the typed fields as the HIGHEST-priority override (recommended). Wire them in buildCRValuesOverlay → the chart keys above, and give the typed CRD fields precedence over configRef, so resolution becomes (highest wins):
typed spec.infrastructure fields (image, replicas, resources, ...) <-- highest
> spec.configRef ConfigMap
> spec.infrastructure labels/annotations
> operator default (GATEWAY_HELM_VALUES_FILE_PATH)
> gateway-helm-chart built-in values <-- lowest
Rationale: typed fields are validated + discoverable, and a .spec change bumps metadata.generation → reliable rollout (unlike a configRef edit, which is only picked up via the fragile ConfigMap-watch/hash path). This mirrors the params model other Gateway API operators use (kgateway GatewayParameters, Envoy Gateway EnvoyProxy). It is also backward-compatible for a GA CRD — additive wiring, no field removal. Behaviour-change caveat: a CR that already sets one of these (ignored today) would start taking effect and now win over its configRef — call this out in release notes.
Option B — Remove the redundant fields. Since configRef already covers them, drop infrastructure.{image,routerImage,replicas,resources,nodeSelector,tolerations,affinity} and storage from the CRD, leaving configRef as the single surface. Simpler, but the CRD is GA, so removal is a breaking schema change that needs a deprecation cycle.
Either way: remove spec.controlPlane.tls (no chart backing), and make the precedence explicit in each field's CRD description: and in the sample CR — e.g. annotate image as "Overrides gateway.controller.image in configRef and the operator default" (Option A) or "Deprecated: set via configRef" (Option B) — so kubectl explain / the YAML itself tells the user what the field does.
The same gap exists on the Gateway API path overlay (gateway_infrastructure_overlay.go also handles only labels/annotations/service).
Version
No response
Related Issue
No response
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with buildCRValuesOverlay in kubernetes/gateway-operator/internal/controller/apigateway_controller.go:757-779, then inspect gateway_infrastructure_overlay.go and the APIGateway CRD definitions and sample CR. Resolve whether typed fields should be wired with precedence or removed, verify the controlPlane and storage mappings against the chart values, and update field descriptions and the sample accordingly. Done means the chosen surface is explicit and no listed field is silently ignored.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, helm, kubernetes
- Domain
- backend-api-design, devops
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100