Files
home-network-k3s-impl/decisions/2026-11-07-l0-externaldns-annotation-prefix.md
T
jakman85andClaude Opus 5.5 9c51f60a35
gate / gate (pull_request) Successful in 2m58s
gate / conformance (pull_request) Skipped
feat(conformance): L0 guard that the external-dns annotationPrefix matches the tree
Add assertion (8) to internal-services-publish-no-public-dns. The external-dns
HelmRelease must declare annotationPrefix explicitly, and every
external-dns annotation in apps/, platform/, runbooks/ and catalog/render.py
must use that prefix. The v0.23.0 default-prefix change on 2026-11-07
ignored the controller: none, target and hostname annotations while
assertions (1)-(3) stayed green.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-07 17:56:12 -06:00

2.5 KiB

date, branch, title
date branch title
2026-11-07 feat/l0-externaldns-annotation-prefix L0 guard — external-dns annotationPrefix must match every external-dns annotation in the tree

What changed

conformance/tests/l0-static/internal-services-publish-no-public-dns/check.sh gains assertion (8). The check is already whole-repo-scoped, so it runs on every gate.

  • (8a) platform/externaldns/helmrelease.yaml must set values.annotationPrefix explicitly, and it must equal the check's ANNOTATION_PREFIX (external-dns.alpha.kubernetes.io/). The check does not trust the upstream default, because that default is what changed.
  • (8b) extraArgs must not carry --annotation-prefix or --enable-legacy-annotation-prefix, so the prefix has one declared place.
  • (8c) Every external-dns-looking annotation key under apps/, platform/ and runbooks/ must use that prefix. The match is any external-dns(.x)*.kubernetes.io/ key.
  • (8d) catalog/render.py must emit no external-dns key under any other prefix.

CONTROLLER_KEY and HOSTNAME_KEY are now derived from ANNOTATION_PREFIX. The Service inventory matches any external-dns prefix variant, not only the alpha one.

Why: on 2026-11-07, external-dns v0.23.0 (whose default prefix is GA) ignored every alpha annotation. Assertions (1) to (3) stayed green, because they prove the annotations are present, not that the controller reads them. See decisions/2026-11-07-public-dns-wan-a-record.md.

This branch is stacked on fix/public-dns-wan-a-record (PR #140). Without that fix, (8a) fails, which is correct. Merge #140 first.

What I verified

Run on the host (PyYAML):

  • the check passes on this tree: check OK: 62 assertions passed.
  • it fails (8a) with origin/main's HelmRelease, which has no annotationPrefix.
  • it fails (8c) when platform/gateway/gateway.yaml's target key is changed to the GA prefix.

Toolbox gate: see the PR description.

What I did NOT verify

  • Whether a future chart could read the prefix from somewhere other than values.annotationPrefix, for example a renamed chart value. (8a) would then pass while the flag silently vanished from the rendered args. Rendering the chart in the gate would close that gap. Not done: it needs network access or a vendored chart in L0.
  • conformance/** is a sensitive path. This PR needs the operator's approving review or /approve-override. The agent did not post one.
  • The header of the sibling chainsaw-test.yaml still says "external-dns v0.21.0". That is cosmetic and I left it alone.