Merge origin/main into feat/keycloak-realm-hosts, and settle README line 184
Validate Helm Charts / Detect changed charts (pull_request) Successful in 4s
Validate Helm Charts / Resource quantities (pull_request) Successful in 17s
Validate Helm Charts / Selector match (pull_request) Successful in 21s
Validate Helm Charts / HTTPRoute match (pull_request) Successful in 14s
Validate Helm Charts / Build keycloak (pull_request) Successful in 8s
Validate Helm Charts / Trivy config keycloak (pull_request) Successful in 26s
Install-test / Install-test keycloak (pull_request) Successful in 3m43s
Validate Helm Charts / Install-test (pull_request) Successful in 3m43s
Validate Helm Charts / Detect changed charts (pull_request) Successful in 4s
Validate Helm Charts / Resource quantities (pull_request) Successful in 17s
Validate Helm Charts / Selector match (pull_request) Successful in 21s
Validate Helm Charts / HTTPRoute match (pull_request) Successful in 14s
Validate Helm Charts / Build keycloak (pull_request) Successful in 8s
Validate Helm Charts / Trivy config keycloak (pull_request) Successful in 26s
Install-test / Install-test keycloak (pull_request) Successful in 3m43s
Validate Helm Charts / Install-test (pull_request) Successful in 3m43s
The rss-bridge Gateway-API round landed while this branch was open, and the two rounds shared exactly one line: the sentence in README.md that carries the whole history of the httproute-match assertion count. Merged rather than rebased on purpose: the branch is already pushed and its history is not rewritten here, so nothing of the other round's text can be lost to a force push. Their half is kept verbatim, including the delta rule they added - that 58/22 and 60/21 were measured on branches which did not contain each other, so the delta is what either number can be trusted for, and the running total belongs to the first branch that holds both. This branch IS that first branch, so the open question is now answered with a measurement instead of an addition: 62 assertions over 22 charts, 0 failed, read off ci/run-httproute-match-test.sh on this merge. keycloak contributes 8 of them, plus the two "not checked" lines for its realm routes' backend-less redirect rules.
This commit is contained in:
8 files changed
+478
-15
No files matched your search
@@ -31,7 +31,7 @@ Every chart has a wiki page of its own — `https://git.jk-dev.de/jlab-cluster/h
|
||||
| `paperless-ngx` | Paperless-ngx | Largest chart: consume CronJob, SMB-connector PV/PVC, pre/post-consumption scripts ConfigMap. Optional `valkey` subchart — **this repo's own chart, from the published index**, off by default and gated on `valkeySubchart.enabled` (not `valkey.enabled`, which the subchart's strict schema rejects). Configured as a **queue** (PVC + `noeviction`), unlike `stalwart`'s cache: `PAPERLESS_REDIS` is the Celery broker, and `allkeys-lru` evicts across the whole keyspace, where a backlog of waiting consume tasks is exactly what LRU reads as cold. The password comes from the **same 1Password item** as the Redis connection, in a third field `auth-conf` holding the complete line `requirepass <password>` — so the password sits in that item **twice** and a rotation has to touch both fields. Two more traps: with the subchart on, `redis-connection-url` in the vault **must** be repointed at `<release>-valkey-service:6379` or the bundled Valkey runs unused, and `valkeySubchart:` must not be erased — a null override deletes the key, Helm reads an unresolvable `condition:` as *enabled*, so erasing the switch turns the subchart **on** (rejected by `values.schema.json`). Never change `valkey/` and this chart in the same PR, see "Chart dependencies" |
|
||||
| `patchmon` | PatchMon | One Deployment (the 2.x server serves frontend and `/api/*` from one process) plus an optional guacd sidecar; OIDC-only sign-in |
|
||||
| `rallly` | Rallly | Deployment, DB/OIDC/SMTP secrets |
|
||||
| `rss-bridge` | RSS-Bridge | Deployment + whitelist ConfigMap; `ingress.hosts` is a required list of host + optional `tlsSecretName`, so several hosts can keep their own existing certificates (documented deviation from the one-TLS-secret rule, see its `values.yaml`) |
|
||||
| `rss-bridge` | RSS-Bridge | Deployment + whitelist ConfigMap; `ingress.hosts` is a required list of host + optional `tlsSecretName`, so several hosts can keep their own existing certificates (documented deviation from the one-TLS-secret rule, see its `values.yaml`) — required only while `ingress.enabled`, since in Gateway mode the names come from `httpRoute.hostnames` and the secret grouping has nothing to group. **The last chart of the Gateway-API sweep (#114)**. Its install-test had failed on the Gitea runner since the move (#51) and the chart was deliberately **not** excluded so that a pass would be noticed — it passed in the conversion PR, on a render byte-identical to `main`, which rules the chart out and leaves the runner |
|
||||
| `samba` | Samba | StatefulSet, users secret + config ConfigMap |
|
||||
| `satisfactory` | Satisfactory game server | StatefulSet, no ingress |
|
||||
| `searxng` | SearXNG | Stateless Deployment + settings ConfigMap (`use_default_settings: true` plus a free-form `settings.extra` passthrough); the signing key is a required `OnePasswordItem`, an external Valkey an optional second one. `ingress.domain` is read twice — Ingress host and `SEARXNG_BASE_URL` — so it stays required with the Ingress switched off |
|
||||
@@ -181,7 +181,11 @@ Three things to know before touching it:
|
||||
- **What is deliberately not checked**, named so the gaps are not mistaken for coverage. *That traffic flows* — no Gateway controller runs in CI and none will, so `Accepted: True` is not obtainable; that claim is simply not made anywhere in this pipeline. *That any redirect is ever served* — the pairing check proves the rendered **object** carries a `RequestRedirect` rule on the bare prefix and nothing more: whether an implementation honours the `statusCode` or declines it and fails the whole route is outside what a render can see. *Mutual exclusion with the Ingress* — each chart aborts its own render when `ingress.enabled` and `httpRoute.enabled` are both true, which is where it belongs: this test renders one configuration per chart, and a rule here would have to assume the switch is chart-global, which may not survive the multi-app charts of the sweep. *Cross-namespace and non-Service backends*, and a rule with no `backendRefs` at all (legal for a filter-only rule) — all three are **reported as "not checked", never counted as passing**. The redirect rule the pairing check demands is itself backend-less, so a chart that satisfies that check also earns one "not checked" line; both verdicts are correct at once.
|
||||
- **Two anti-vacuum guards**, because the convention ships `httpRoute.enabled: false` and this test would otherwise be green over nothing. `ci/httproute/<chart>.yaml` is a render-only overlay applied **last** whose one job is to put a chart into Gateway mode — and a chart that *has* one and still renders no route **fails**. On top of that the run fails if **no assertion at all** held anywhere. `cyberchef` is exercised through its ordinary install-test fixture (which installs in Gateway mode, see below), every other converted chart through its overlay. For a multi-app chart the overlay also has to enter every shape the template has: `ci/httproute/freesailarr.yaml` moves one app onto a host of its own so that the shared-host route *and* the per-app route are both rendered.
|
||||
|
||||
Measured in CI (run 719, the pilot): **30 charts, 4 assertions held**, whole job 13 s including checkout and the Helm setup, no cluster. Group 1 took that to 20 assertions over 10 charts and group 2 to 36 over 15; the prefix/redirect pairing of Gitea #118 adds the first check since the pilot rather than a chart, which brought it to 37 over 15 — one assertion for `freesailarr`'s `/qbittorrent`, plus one more "not checked" line for the backend-less redirect rule it demands. **Group 3 takes it to `56` assertions over `21` charts**, which is the sweep finished except for the frozen `rss-bridge`. Group 3's 19 come from six charts and three of them contribute more than one route: `keycloak` 4 (public and admin routes), `matrix-synapse` 4 (homeserver and delegation routes), `homeassistant` 5 (two routes, three rules — its overlay is the only one in the repo that has to *supply* hostnames, since the chart has no `ingress.domain`), `bulwark` 2, `stalwart` 2, `ytdlp-web-player` 2. **The realm hostnames of Gitea #122 add `4`**: `keycloak`'s share goes from 4 to 8, because its two realm routes each earn one `parentRefs` assertion and one `backendRefs` assertion on their prefix rule, plus one "not checked" line each for their backend-less redirect rule (`keycloak: ok (8 assertion(s) held, 2 not checked)`). Measured as `60` over `21` charts on the branch that added them, which did **not** contain the `rss-bridge` conversion — the two landed in parallel, so the **delta** is the durable figure here and the running total is whatever the first CI run on `main` prints after both. No new *check*: the two realm routes are objects, and the prefix/redirect pairing of #118 deliberately does **not** fire on them — it is scoped to rules that strip a prefix with a `ReplacePrefixMatch` rewrite, and a realm route strips nothing, it redirects the bare root of a hostname that serves one realm. The fail path was exercised rather than assumed: a Service renamed in the route, a port the Service does not expose, a port left out entirely, an emptied `parentRefs` with the chart's own guard disabled, an overlay that renders no route, a run with zero assertions, and — for the pairing — both the redirect rule deleted outright and the redirect pointed at a path other than the one stripped; each produced a `FAIL` naming both sides and a non-zero exit.
|
||||
Measured in CI (run 719, the pilot): **30 charts, 4 assertions held**, whole job 13 s including checkout and the Helm setup, no cluster. Group 1 took that to 20 assertions over 10 charts and group 2 to 36 over 15; the prefix/redirect pairing of Gitea #118 adds the first check since the pilot rather than a chart, which brought it to 37 over 15 — one assertion for `freesailarr`'s `/qbittorrent`, plus one more "not checked" line for the backend-less redirect rule it demands. Group 3 took it to `56` assertions over `21` charts, from six charts of which three contribute more than one route: `keycloak` 4 (public and admin routes), `matrix-synapse` 4 (homeserver and delegation routes), `homeassistant` 5 (two routes, three rules — its overlay was the first in the repo that has to *supply* hostnames, since the chart has no `ingress.domain`), `bulwark` 2, `stalwart` 2, `ytdlp-web-player` 2. **`rss-bridge` finishes the sweep at `58` assertions over `22` charts** — read on this branch, which does **not** contain the realm-hostname round of Gitea #122 (measured separately at `60` over `21`, on a branch that did not contain `rss-bridge`). **Neither total includes the other, so the figure to trust from either is the delta**; the running total was therefore read off the first branch that contained both — the realm-hostname branch rebased onto this one — and it is **`62` assertions over `22` charts**, `0` failed. `keycloak` contributes `8` of them: one `parentRefs` and one `backendRefs` assertion for each of its four routes, the two realm routes adding one "not checked" line each for their backend-less redirect rule (`keycloak: ok (8 assertion(s) held, 2 not checked)`). The #118 prefix/redirect pairing deliberately does **not** fire on those two: it is scoped to rules that strip a prefix with a `ReplacePrefixMatch` rewrite, and a realm route strips nothing — it redirects the bare root of a hostname that serves one realm. The delta here is one route, so two assertions, and its overlay is the **second** that has to supply hostnames — for a different reason than `homeassistant`'s, which is worth keeping apart. `homeassistant` has no `httpRoute.hostnames` key at all and its overlay supplies the names through `ingress.hosts`; `rss-bridge` *has* the key and its overlay fills it, because this chart has no `ingress.domain` to fall back to either but its hostnames are unambiguous (one Service, one path).
|
||||
|
||||
**And in the same PR that chart's install-test went green, which is the event Gitea #51 was waiting for.** It had failed on the Gitea runner for months (uid 33 unable to read `/app/index.php`, startup probe 403 through its whole budget), and the chart was deliberately kept *out* of `ci/excluded-charts.txt` precisely so that the day it passed would be noticed rather than silenced. It passed: k3d cluster up, `helm install` in Ingress mode, pod `1/1 Ready` in 22 s with 0 restarts, and no `Permission denied` anywhere in the job. **The chart cannot be the reason, and that is measured rather than argued** — the rendered output for the fixture values is byte-identical to `origin/main`, so the pod spec that installed is exactly the one `main` produces. The implicated layer is the runner, which is where #51 had already put the burden of proof. Two cautions belong with the result: **nobody has identified what changed on the runner**, and a green test does not explain itself — it reproduced across two consecutive runs on two different commits of that PR, which is two data points rather than one, but still no cause; and the install covers **Ingress** mode, since that is what the fixture installs — so this chart's Gateway mode stays render-only, exactly like its 21 siblings rather than worse than them.
|
||||
|
||||
The fail path was exercised rather than assumed: a Service renamed in the route, a port the Service does not expose, a port left out entirely, an emptied `parentRefs` with the chart's own guard disabled, an overlay that renders no route, a run with zero assertions, and — for the pairing — both the redirect rule deleted outright and the redirect pointed at a path other than the one stripped; each produced a `FAIL` naming both sides and a non-zero exit.
|
||||
|
||||
### Install-test (PR pipeline stage 2)
|
||||
|
||||
@@ -386,7 +390,7 @@ These guidelines are **binding for every current and future chart** in this repo
|
||||
- `ingress.className` selects the ingress class and defaults to `nginx`.
|
||||
- `ingress.annotations` takes optional extra annotations that are merged with the cert-manager `cluster-issuer` annotation the chart always sets.
|
||||
- The TLS secret is named `tls-<release>-<chart>-ingress`.
|
||||
- **A set of objects publishing ONE backend under hostnames the chart does not own is the third admissible shape, and it buys its secret name and its issuer per entry (Gitea #122).** Where a chart's app serves several tenants from one deployment and each wants a hostname of its own — `keycloak`'s realms are the case this was written for — the hostnames come as a values list and the chart renders one object per entry. Two convention rules do not survive that, and both deviations are **required**, not merely tolerated: the TLS secret name is a per-entry value with **no** default, because these hostnames already have certificates and several entries typically share one (a wildcard for a zone), so a derived `tls-<release>-<chart>-...` name per entry would ask cert-manager for a second certificate for a name that is already covered — one ACME order per hostname, for nothing; and the cert-manager annotation becomes **optional per entry**, because cert-manager keys a Certificate by the secret it writes, so of several objects naming one secret exactly one may carry it. That is the same deliberate omission the qBittorrent object in `freesailarr` makes, for the same reason, and it is why the secret name is required rather than defaulted: a chart that invents the name cannot also leave the issuing to somebody else. Annotations are per entry too, since the set is not uniform across the hostnames. Object names carry the **list index**, for the reason spelled out in the homeassistant bullet below — a hostname is not a dependable object-name fragment, so reordering the list renames and recreates the objects — and the entries render in **both** routing modes — a mode-asymmetric feature is not admissible, which is also why the per-entry `parentRefs` exists as the counterpart of the per-entry class.
|
||||
- **A set of objects publishing ONE backend under hostnames the chart does not own is the third admissible shape, and it buys its secret name and its issuer per entry (Gitea #122).** Where a chart's app serves several tenants from one deployment and each wants a hostname of its own — `keycloak`'s realms are the case this was written for — the hostnames come as a values list and the chart renders one object per entry. Two convention rules do not survive that, and both deviations are **required**, not merely tolerated: the TLS secret name is a per-entry value with **no** default, because these hostnames already have certificates and several entries typically share one (a wildcard for a zone), so a derived `tls-<release>-<chart>-...` name per entry would ask cert-manager for a second certificate for a name that is already covered — one ACME order per hostname, for nothing; and the cert-manager annotation becomes **optional per entry**, because cert-manager keys a Certificate by the secret it writes, so of several objects naming one secret exactly one may carry it. That is the same deliberate omission the qBittorrent object in `freesailarr` makes, for the same reason, and it is why the secret name is required rather than defaulted: a chart that invents the name cannot also leave the issuing to somebody else. Annotations are per entry too, since the set is not uniform across the hostnames. Object names carry the **list index**, for the reason spelled out in the homeassistant bullet below — a hostname is not a dependable object-name fragment, so reordering the list renames and recreates the objects — and the entries render in **both** routing modes: a routing value in this repository is mode-independent by design, so a feature rendering in one mode only would silently disappear when an installation switched. That is also why the per-entry `parentRefs` exists, as the counterpart of the per-entry class.
|
||||
- **Documented exception — homeassistant, and it extends to the Gateway mode**: keeps its upstream-style flexible ingress values (host/tls lists, no required values); only its `ingress.className` default follows the standard (`nginx`, clearable to omit the field). Because it has **no `ingress.domain`**, it has **no `httpRoute.hostnames`** either — the second chart without that key after `freesailarr`, and the schema rejects it outright so the absence is enforced rather than merely intended. The hostnames and the paths come from `ingress.hosts`, which is therefore read in **both** modes and is not an Ingress-only value, and the chart renders **one `HTTPRoute` per entry** of that list with one rule per path of the entry. One object carrying several hostnames would be wrong rather than merely different: an `HTTPRoute`'s rules apply to *every* hostname of the object, and per-host paths are this chart's whole point. `ingress.className`, `ingress.tls` and `ingress.annotations` are not read in Gateway mode. Route names carry the entry's **index**, not its hostname (a hostname is not a dependable object-name fragment), so reordering `ingress.hosts` renames routes and therefore recreates rather than edits them — harmless, since a route holds no state and no certificate, but worth knowing before it looks like a bug. Its `pathType` default is the awkward one; see the `ImplementationSpecific` rule in the Gateway-API bullets below.
|
||||
- **A shared domain with sub-paths is the second admissible ingress shape.** Where a chart exposes several apps, they may either each take a host of their own or share one host and be told apart by path (`domain.tld/sonarr`, `domain.tld/radarr`, …) — one DNS name and one certificate for the whole bundle. The rules for the shared shape: the domain is a single value (`ingress.host`), each app's path is its own value defaulting to `/<app>`, the paths render in one Ingress object `<release>-<chart>-ingress` with the standard TLS secret `tls-<release>-<chart>-ingress`, and an app that carries a host of its own always wins and keeps its own object — so both shapes mix without extra values. An app that needs a per-path proxy annotation (`rewrite-target` is per **object**, not per path) gets its own object on the same host, repeating the same TLS secret name and **omitting** the cert-manager annotation, so that exactly one certificate is requested. Apps that cannot serve a base path must be rendered at `/` or refused with a `fail` — never rendered somewhere they provably cannot work.
|
||||
- **The Gateway API is the second routing mode, and it is implementation-neutral by construction (Gitea #114).** A chart offers it through one values block, off by default:
|
||||
@@ -404,7 +408,7 @@ These guidelines are **binding for every current and future chart** in this repo
|
||||
- **A value, not auto-detection.** `.Capabilities.APIVersions` is unreliable at template time, and an `HTTPRoute` without the Gateway-API CRDs fails at install time — so a chart that guessed would sometimes render an object the cluster rejects and sometimes silently render nothing.
|
||||
- **Mutually exclusive with `ingress.enabled`**, enforced by a `fail` that names **both** value paths. Two paths onto the same Service under one hostname is a conflict at DNS level already; a migration runs over a **second hostname** (`httpRoute.hostnames` set explicitly while the Ingress keeps `ingress.domain`), never over parallel operation.
|
||||
- **`parentRefs` is mandatory in Gateway mode**, enforced by a `fail` on the empty list. A route without a parent attaches to nothing and is simply inert — created, schema-valid, rejected by nobody, reported by nothing.
|
||||
- **One source of truth for the hostname.** Empty `hostnames` means `[ingress.domain]`; two values that have to agree drift apart. `ingress.domain` is therefore read in Gateway mode too — it names the release's public hostname and is not an Ingress switch.
|
||||
- **One source of truth for the hostname.** Empty `hostnames` means `[ingress.domain]`; two values that have to agree drift apart. `ingress.domain` is therefore read in Gateway mode too — it names the release's public hostname and is not an Ingress switch. After the sweep there are **three** shapes here, and which one a chart gets follows from its values rather than from taste: a chart with an `ingress.domain` falls back to it (the default, most charts); a chart with no `ingress.domain` whose names could not be attributed — `freesailarr` to one of ten apps, `homeassistant` to one host entry and therefore one set of paths — has **no `hostnames` key at all** and reads the names where they already live; and `rss-bridge` has the key as a **mandatory** value with no fallback, because it has no `ingress.domain` either but its names *are* unambiguous (one Service at `/`), while the `ingress.hosts` list it would otherwise reuse carries per-host `tlsSecretName` values that address nothing once TLS sits on the listener. The rule behind all three: a hostname list is admissible exactly where it can say what it belongs to, and reusing an Ingress structure whose other half is meaningless in this mode is not a saving.
|
||||
- **`NOTES.txt` says which mode is active**, as `keycloak` already does for its cases, and names what the mode costs.
|
||||
- **What has no counterpart, and must be said rather than rebuilt.** The Gateway API has no annotation channel for controller behaviour. `rewrite-target` has a real equivalent (the `URLRewrite` filter in a rule); **`proxy-body-size` has none** — an upload limit is implementation-specific policy, so a chart that depends on one must print in its Gateway-mode `NOTES.txt` that the limit is **not enforced** and has to be set at the Gateway. Charts that *set or recommend* one carry that disclosure: `calibre-web-automated`, `outline`, `paperless-ngx`, `zipline` since group 2, `bulwark` and `matrix-synapse` since group 3. `garage` *depends* on one without setting it: its `ingress.annotations` comment tells the operator to set `proxy-body-size: "0"` because ingress-nginx's 1 MB default truncates S3 uploads. Measured while sweeping group 1 — "sets no behaviour-bearing annotation" is not the same question as "needs none", and the sweep screens on the second one. `freesailarr` is the mirror image of `garage` and was measured in group 2: it sets no body-size annotation and needs none itself, but `ingress.annotations` is the only lever an operator has for one (qBittorrent takes torrent-file uploads), so its Gateway-mode `NOTES.txt` says that an annotation set there is gone. The same applies to auth annotations in front of an app with no login of its own: in Gateway mode that escape hatch does not exist in the chart at all (`cyberchef`, `searxng`), and so does any annotation a chart documents as its only lever for a response header (`bentopdf`: `X-Robots-Tag`).
|
||||
- **Screen the LIVE object, not only the chart — group 3's lesson, and the generalisation of Gitea #118.** A chart can read as correct while the running system fills a gap of the chart with an annotation the **operator** set, and the Gateway mode drops `ingress.annotations`, so it drops the compensation with it. At #118 that was found *after* shipping, on `freesailarr`, where the annotation was a redirect nobody would have looked for in the chart. Group 3 measured it beforehand with read-only `kubectl` against the live cluster, and **four of its six charts carried such an annotation that the chart never sets**: `keycloak` (`proxy-buffer-size: 16k` and `proxy-buffers-number: 4`, on *both* of its Ingress objects), `matrix-synapse` (`proxy-body-size: 50m`, plus the `nginx.org/client-max-body-size` twin for the other nginx controller, plus a `configuration-snippet`), `stalwart` (the whole `enable-cors` block), `bulwark` (`proxy-body-size: 25m`). None of them appears in a `git grep` of this repository, because no template sets any of them — the only hits are the *documentation* that recommends two of them. **The measurement at the live object is part of the procedure, not a flourish**, and reading the chart alone is not a substitute for it.
|
||||
@@ -417,11 +421,11 @@ These guidelines are **binding for every current and future chart** in this repo
|
||||
- `freesailarr` (group 2), whose `freesailarr.sharedIngressApps` was gated on `ingress.enabled` and is read by the `<APP>__SERVER__URLBASE` environment variables as well as by the routing objects. In Gateway mode that list would have come out **empty**, so Radarr, Sonarr and Prowlarr would have been told no base path while their routes served them under `/radarr`, `/sonarr`, `/prowlarr` — a UI whose assets and API calls are linked at the host root, behind a Ready pod. The two guards living in that helper (seerr/mediathekarr only at `/`, no duplicate paths on the shared host) would have gone unenforced in that mode for the same reason. Helper `freesailarr.published`.
|
||||
- `ytdlp-web-player` (group 3), the one this file had listed as still open, and the find with the sharpest consequence. Its `ytdlp-web-player.validate` guard — which refuses to publish the application and the bundled oauth2-proxy on the **same host** — was gated on `ingress.enabled`, so in Gateway mode it went silent. **And that guard is needed more in Gateway mode, not less.** In Ingress mode ignoring it fails loudly: ingress-nginx's admission webhook rejects the second Ingress and the Fleet bundle lands in `ErrApplied`. In Gateway mode **the webhook never fires** — it compares Ingress objects with Ingress objects, and an `HTTPRoute` is a different kind — so nothing rejects anything, both objects stay valid, and one hostname is served over two data paths that are *not* equivalent: the proxy's Ingress goes through **authentication**, the chart's `HTTPRoute` goes straight to the application. Which one a client reaches depends on what DNS resolves to, so it is an authentication bypass that comes and goes with a record, reported by nothing. Helper `ytdlp-web-player.published`, and the Gateway-mode abort carries its own message saying exactly that.
|
||||
|
||||
All three are now closed, and the screen was run over all six charts of group 3 rather than only the suspected one.
|
||||
All three are now closed, and the screen was run over all six charts of group 3 rather than only the suspected one — and over `rss-bridge` as the last chart, where it came back **clean**: outside its Ingress template the only readers of an ingress value are `NOTES.txt`, which knows its own mode, and the `rss-bridge.tlsGroups` helper, which is called only from behind `ingress.enabled`. The application takes no base URL and no hostname in its environment, so there is nothing to compute from the switch and no `published` helper is needed. **A clean result is worth recording too**: the screen's value is that it is run, not that it always finds something, and "this chart needed no helper" is a measurement rather than an omission.
|
||||
- **A subchart does not come along, and that has to be said where somebody will look for it.** `ytdlp-web-player`'s oauth2-proxy dependency has **no Gateway-API support** and this repo does not patch upstream charts (see "Chart dependencies"), so it renders an Ingress or nothing. In the *recommended* configuration — the proxy in the data path, owning the host, the chart's own routing object off — the object that publishes the release is therefore **the subchart's Ingress in both of the chart's modes**, and setting `httpRoute.enabled` there changes nothing about how the host is served. The chart's own route is for the proxy-disabled case or for the application on a host of its own, which is the documented unauthenticated bypass. Stated in the template header, in `values.yaml`, in the schema and in the proxy branch of `NOTES.txt`, because an operator migrating hosts would otherwise set the value and wonder why nothing moved.
|
||||
- **CI**: either the chart's install-test fixture installs in Gateway mode, or it gets a render-only overlay at `ci/httproute/<chart>.yaml` — otherwise `ci/run-httproute-match-test.sh` is green over nothing for it, which that test fails on. An overlay for a multi-app chart has a second job: it must enter **every** shape the template has, or the branch nobody exercised is the one that breaks. `ci/httproute/freesailarr.yaml` gives one app a host of its own so both the shared-host route and the per-app route render.
|
||||
|
||||
Reference implementation: `template-chart/templates/xxx.httproute.yaml`. Pilot: `cyberchef`. Group 1 — the charts rendering one Ingress with no behaviour-bearing annotation — followed: `bentopdf`, `garage`, `patchmon`, `rallly`, `searxng`, `sure`, `urlaubsverwaltung`, `voucher-vault`. Group 2 — the charts whose behaviour hangs off an nginx annotation — followed: `calibre-web-automated`, `outline`, `paperless-ngx`, `zipline` (all four `proxy-body-size`) and `freesailarr` (`rewrite-target`). **Group 3 — the special shapes — finishes the sweep**: `homeassistant`, `keycloak`, `bulwark`, `matrix-synapse`, `stalwart`, `ytdlp-web-player`. That leaves exactly one chart, `rss-bridge`, which is frozen for changes (#51) and is why **#114 cannot be closed while #51 is open**.
|
||||
Reference implementation: `template-chart/templates/xxx.httproute.yaml`. Pilot: `cyberchef`. Group 1 — the charts rendering one Ingress with no behaviour-bearing annotation — followed: `bentopdf`, `garage`, `patchmon`, `rallly`, `searxng`, `sure`, `urlaubsverwaltung`, `voucher-vault`. Group 2 — the charts whose behaviour hangs off an nginx annotation — followed: `calibre-web-automated`, `outline`, `paperless-ngx`, `zipline` (all four `proxy-body-size`) and `freesailarr` (`rewrite-target`). Group 3 — the special shapes: `homeassistant`, `keycloak`, `bulwark`, `matrix-synapse`, `stalwart`, `ytdlp-web-player`. **`rss-bridge` finishes the sweep**, as the twenty-second and last chart: 22 charts carried an Ingress template and 21 an HTTPRoute template, and the difference was exactly this one. It had been held back as frozen for changes by #51 — a runner defect, not a property of the chart — and the earlier claim that **#114 could not be closed while #51 was open no longer holds**: the maintainer lifted that freeze, so #114 closes with the chart converted while **#51 stays open**, since the runner defect is worked around for this purpose rather than fixed. Its shape: one `HTTPRoute` carrying **all three** of its hostnames, because nothing differs per host (every name serves the same Service at `/`, measured on the live Ingress), so `spec.hostnames` as a list is the whole answer and a second object would repeat one rule. It is also the only chart of the sweep whose Gateway branch has **no loss to document** — its live Ingress carries no `nginx.ingress.kubernetes.io` annotation at all, so the group-3 screen came back empty. Its install-test, red since the move (#51), **went green in the conversion PR** with a pod `Ready` in 22 s and no `Permission denied`; since that PR's rendered defaults are byte-identical to `origin/main`, the chart is ruled out as the cause and the runner is the implicated layer. That green covers Ingress mode, which is what the fixture installs, so the Gateway mode of this chart is render-only like every other chart's.
|
||||
|
||||
**Three of #114's descriptions of the group-3 shapes did not survive contact with the charts**, and the corrected list is worth having here because it is the one somebody will copy from:
|
||||
|
||||
|
||||
Reference in new issue
Block a user