Skip to content

[dmt] add ingress/gw-api linters - #474

Merged
ldmonster merged 2 commits into
mainfrom
add-ingress-gateway-api-linters
Sep 16, 2026
Merged

ldmonster merged 2 commits into
mainfrom
add-ingress-gateway-api-linters

Conversation

@miklezzzz

@miklezzzz miklezzzz commented Sep 6, 2026

Copy link
Copy Markdown
Member

This pr adds Ingress / Gateway API linting rules:

Adds six rules to the templates linter that enforce ingress and Gateway API hygiene across Deckhouse modules. Every rule is severity-configurable (error/warn) and disable-/exclude-able via .dmtlint.yaml, and each is gated so it only runs on modules that actually render the resource kind it cares about — a module with no Ingress, HTTPRoute, or ListenerSet is never touched.

Enablement — a resource you ship must be switchable off

ingress-enablement flags any template that emits a kind: Ingress but never references helm_lib_module_ingress_enabled. Without that guard the Ingress renders unconditionally and can't be disabled through global.modules.ingress.enabled or the module's own .ingress.enabled override. The finding names the exact .Values paths and the {{- if eq (include …) "true" }} guard to add.

gateway-enablement is the Gateway API counterpart: a template emitting kind: HTTPRoute or kind: ListenerSet must reference helm_lib_module_gateway_enabled. Unlike Ingress there is no safe default gateway, so that helper checks both the enable flag and that a Gateway actually resolves.

Both use a same-file textual heuristic (does this file emit the kind and mention the helper?) rather than a full Helm control-flow parser — a deliberate trade-off documented in the code, since in practice the guard and the manifest it protects live in the same file.

Migration — stop using annotations the platform has replaced

deprecated-httproute-annotations flags banned annotation keys anywhere in a template (plain YAML or inside a Helm expression). It currently bans alb.network.deckhouse.io/response-headers-to-add, pointing authors at the native Gateway API ResponseHeaderModifier filter and including a ready-to-paste replacement snippet. The banned list is a single data structure — adding another annotation is one entry.

Certificate reuse — copy a CustomCertificate once, share it across flows

https-certificate-reuse applies to modules that serve HTTPS over both Ingress and Gateway API. In CustomCertificate mode the two flows must share one copied secret: the Ingress manifest references it with the plain helm_lib_module_https_secret_name form (list . "base"), and the HTTPRoute/ListenerSet manifest with the two-prefix form (list . "base" "override") that links back to the same base. The rule scans every template (splitting files on --- so a HTTPRoute bundled with its cert-manager Certificate is classified per-document) and reports five things: a prefix copied more than once, an Ingress using the two-prefix form, a Gateway API manifest using the plain form, an override that's also independently copied, and — from the copy calls alone — a -ingress-tls / -httproute-tls pair that should have been one copy.

HTTP → HTTPS redirect — the pair that guarantees redirects actually happen

These two complement each other so an HTTPS host can't silently refuse plain-HTTP requests:

listenerset-redirect requires every hostname a ListenerSet exposes over HTTPS to also have a plain-HTTP (port 80) listener, so HTTP traffic has somewhere to be redirected from.

httproute-redirect then requires each of those port-80 redirect sections to be backed by an HTTPRoute whose parentRef targets the section (by name/section, cross-namespace–aware) with a RequestRedirect filter to HTTPS (scheme: https or port: 443).

Because rendered hostnames come from publicDomainTemplate and aren't known at lint time, exclusions for both are keyed by listener section name ({name: , section:

}, either field empty = wildcard) rather than by hostname.

Wiring & configuration
Registered in the templates linter (templates.go) and the static rule set; each has a mapstructure key matching its rule name.
Exclusions: the four file-scanning rules take PathRuleExclude (files: + directories:); the two redirect rules take a list of {name, section} entries.
Docs: every rule has a ### section with examples in pkg/linters/templates/README.md; coverage is unit tests per rule plus auto-discovered test/e2e fixtures (including a negative gating case proving the rules stay silent on modules with no ingress/Gateway objects).

@miklezzzz miklezzzz self-assigned this Sep 6, 2026
@miklezzzz
miklezzzz force-pushed the add-ingress-gateway-api-linters branch from cb71ca0 to c684b37 Compare September 15, 2026 09:29
Signed-off-by: Mikhail Scherba <mikhail.scherba@flant.com>
Signed-off-by: Mikhail Scherba <mikhail.scherba@flant.com>
@miklezzzz
miklezzzz force-pushed the add-ingress-gateway-api-linters branch from 270035f to 8977a29 Compare September 16, 2026 12:41
@ldmonster ldmonster changed the title add ingress/gw-api linters [dmt] add ingress/gw-api linters Sep 16, 2026
@ldmonster
ldmonster merged commit 000ff31 into main Sep 16, 2026
8 checks passed
@ldmonster
ldmonster deleted the add-ingress-gateway-api-linters branch September 16, 2026 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants