Skip to content

fix(chart): harden Gateway API routing and fix fatal secrets-loop scoping - #126

Merged
MusaMisto merged 1 commit into
mainfrom
feat/gateway-api-hardening
Aug 31, 2026
Merged

fix(chart): harden Gateway API routing and fix fatal secrets-loop scoping#126
MusaMisto merged 1 commit into
mainfrom
feat/gateway-api-hardening

Conversation

@MusaMisto

Copy link
Copy Markdown
Member

Why

The mtm chart is deployed six times across the estate — funride, kwickbox and tamweelna × staging/production — and all six are about to move onto the shared Cilium Gateway. Gateway API support was merged to main in June, but the schema had four latent failure modes, two of them fatal and two silent.

Worth stating up front: the gateway value schema already matches s9genericchart-v2 exactlycharts/default/templates/httproute.yaml was byte-identical to that chart's, and the gateway: values block is semantically identical apart from enabled: false (correct here, since this chart keeps its ingress path). No schema changes in this PR. It only hardens what was already there.

What changed

Failure Before After
gateway: null / ingress: null nil-pointer render error renders no route
Route with empty backendRef: interface conversion: interface {} is nil falls back to the chart's own Service
Route with no path renders value: (null) — Helm accepts, API server rejects fails loudly via required
backendRef.weight: 0 silently discarded (with treats 0 as falsy) honoured via hasKey
Any release setting secrets.* can't evaluate field Values in type string — total render failure renders correctly

The last one is the most serious and is unrelated to Gateway API: inside range $key, $values := .Values.secrets, . is rebound to the map value (a string), so template "project.fullname" . blew up. $root was already captured on the line above for exactly this purpose and never used. It is masked today only because every caller passes the connection string through the top-level db value rather than secrets.

Verification

  • helm lint --strict — clean (only the pre-existing icon is recommended INFO).
  • Each of the four failures reproduced on main first, then confirmed fixed.
  • Regression proof: rendered the chart against the live helm get values output of all six releases, plus chart defaults and gateway-enabled defaults — 8/8 byte-identical before vs after. No existing deployment changes behaviour.
  • The resulting HTTPRoute passes kubectl apply --dry-run=server against the live SBN gateway cluster (k8s v1.36.3, HTTPRoute v1 served and storage).

Follow-up (not in this PR)

The published chart is the real blocker: charts.sf9.io has mtm-6.0.8 (Aug 2025) and GHCR OCI has 6.0.7neither contains httproute.yaml, because the newest git tag (6.0.9, Feb 2026) predates the June gateway merge. Any deploy passing gateway.* against a published chart today silently renders an Ingress instead. Merging this PR triggers CI and publishes the first gateway-capable chart version.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VHkpqv6dB6wjALyFe9ocMU

…ping

The gateway value schema already matched s9genericchart-v2 exactly (the
HTTPRoute template is byte-identical), so this changes no schema. It fixes
the four ways that schema could fail silently or fatally, which matters
because the mtm chart backs six live releases (funride, kwickbox and
tamweelna x staging/production) that are all about to move onto the shared
Cilium Gateway.

- httproute/ingress/NOTES: guard `.Values.gateway` and `.Values.ingress`
  before dereferencing `.enabled`. Nulling either block raised a
  nil-pointer error instead of simply rendering no route.
- httproute: normalise `backendRef` to a dict before use. A route carrying
  an explicitly empty `backendRef:` — the exact shape produced by
  commenting out the two children shipped in values.yaml — crashed with
  "interface conversion: interface {} is nil".
- httproute: `path` is now `required`. It previously rendered `value:`
  (null), producing an HTTPRoute that Helm accepted and the API server
  rejected.
- httproute: emit `backendRef.weight` via `hasKey` rather than `with`, so
  an explicit `weight: 0` is honoured instead of silently discarded.
- deployment: pass `$root` to project.fullname inside the `.Values.secrets`
  range. `.` is rebound to the map value there, so ANY release that set
  `secrets.*` failed to render with "can't evaluate field Values in type
  string". `$root` was already captured for this and never used.

Verified: `helm lint --strict` clean; all four failures reproduced before
and confirmed fixed after; and rendering the chart against the live
user-supplied values of all six production/staging releases produces
byte-identical output, so no existing deployment changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHkpqv6dB6wjALyFe9ocMU
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: simplify9/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b8314d7c-b82b-4f9a-b6f3-e6f58a51996a

📥 Commits

Reviewing files that changed from the base of the PR and between 0608900 and fe0c426.

📒 Files selected for processing (4)
  • charts/default/templates/NOTES.txt
  • charts/default/templates/deployment.yaml
  • charts/default/templates/httproute.yaml
  • charts/default/templates/ingress.yaml

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (1)
Review Helm chart changes for insecure defaults, exposed services,

⚙️ CodeRabbit configuration file

Files:

  • charts/default/templates/NOTES.txt
  • charts/default/templates/deployment.yaml
  • charts/default/templates/httproute.yaml
  • charts/default/templates/ingress.yaml
🪛 LanguageTool
charts/default/templates/NOTES.txt

[style] ~10-~10: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...nd }}
{{- else if and .Values.ingress .Values.ingress.enabled }}
{{- range .Values.i...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🪛 YAMLlint (1.37.1)
charts/default/templates/httproute.yaml

[error] 1-1: syntax error: expected the node content, but found '-'

(syntax)

charts/default/templates/ingress.yaml

[error] 1-1: syntax error: expected the node content, but found '-'

(syntax)

🔇 Additional comments (4)
charts/default/templates/deployment.yaml (1)

127-134: LGTM!

charts/default/templates/NOTES.txt (1)

2-2: LGTM!

Also applies to: 10-10

charts/default/templates/httproute.yaml (1)

1-11: LGTM!

Also applies to: 22-32, 45-55, 66-77

charts/default/templates/ingress.yaml (1)

1-6: LGTM!


📝 Walkthrough

What changed

  • Nil-guarded gateway and ingress values.
  • Added required validation for route path and parentRefs.name.
  • Used the chart Service when backendRef is empty.
  • Preserved explicit backendRef.weight: 0.
  • Fixed root-context scoping while iterating over secrets.

Risk

risk:low

The changes affect Helm rendering and Gateway API routing. Invalid or incomplete route values now fail validation instead of causing template errors or producing ambiguous resources.

Security-sensitive areas

No direct security control changed. Gateway and Ingress rendering can affect external exposure. The secrets change fixes template evaluation scope and does not change secret contents or access permissions.

Test coverage impact

  • Strict linting passes.
  • Four failure cases were reproduced and resolved.
  • Rendering remains byte-identical for six live releases and default values.
  • Server-side validation passes for the resulting HTTPRoute.

Operational concerns

  • No schema, migration, or manual rollout step is required.
  • Existing valid configurations should render unchanged.
  • Review route values that omit path, parentRefs.name, or backendRef.
  • Rollback requires reverting the chart version if routing behavior causes an issue.

Walkthrough

The chart templates now guard optional routing values, validate required HTTPRoute fields, preserve explicit zero weights, and use the root context when resolving deployment secret names.

Changes

Helm template hardening

Layer / File(s) Summary
Routing condition guards
charts/default/templates/NOTES.txt, charts/default/templates/ingress.yaml, charts/default/templates/httproute.yaml
Gateway and Ingress conditions now verify configuration objects before reading enabled.
HTTPRoute field validation
charts/default/templates/httproute.yaml
parentRefs.name and route path are required. Empty backendRef values use a dictionary. Explicit weight: 0 is preserved.
Secret iteration context
charts/default/templates/deployment.yaml
Secret fullname resolution uses the captured root context during range iteration.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to fe0c4

The chart now safely handles null or empty Gateway settings, validates required route names, preserves zero weights, and fixes secrets rendering; no actionable merge-blocking risk remains after normal checks and review.

Suggested labels: infra, risk:high

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: hardening Gateway API routing and fixing fatal secrets-loop scoping.
Description check ✅ Passed The description directly explains the routing safeguards, scoping fix, verification, and deployment impact.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (4 skipped: 4 unsupported.)


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@MusaMisto MusaMisto self-assigned this Aug 31, 2026
@MusaMisto MusaMisto added bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request and removed bug Something isn't working labels Aug 31, 2026
@MusaMisto
MusaMisto merged commit 3996cba into main Aug 31, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant