Skip to content

Commit e93c3db

Browse files
committed
feat(gateway): align _namespace.gateway propagation with tenant.gatewayEffective
Two related fixes for the gap where the tenant chart's gateway HelmRelease materialises but child apps (harbor, bucket) silently fall back to ingress-nginx: - packages/apps/tenant/templates/namespace.yaml: switch the _namespace.gateway resolution from raw .Values.gateway to tenant.gatewayEffective. This is the same helper consulted by gateway.yaml (HelmRelease render), so per-tenant Gateway materialisation and child-app HTTPRoute / Ingress selection now stay in lockstep — including the auto-default for derived-apex tenants. - packages/system/cozystack-basics/templates/cozystack-values-secret.yaml: add a conditional gateway field to the tenant-root cozystack-values Secret. cozystack-basics is the only writer of _namespace.* for tenant-root (apps/tenant chart skips tenant-root via the existing ne 'tenant-root' gate). Without this line, tenant-root apps read _namespace.gateway as empty and route to ingress even when the platform's gateway.enabled flag is on. Conditional on _cluster.gateway-enabled='true' so non-Gateway clusters keep the empty value. Test fixture in cozystack-basics/tests/cozystack-values-secret_test.yaml pins the conditional and the regression-guard that the other four _namespace keys (etcd, ingress, monitoring, seaweedfs) stay unconditional. Assisted-By: Claude <[email protected]> Signed-off-by: Aleksei Sviridkin <[email protected]>
1 parent c92ff37 commit e93c3db

3 files changed

Lines changed: 116 additions & 11 deletions

File tree

‎packages/apps/tenant/templates/namespace.yaml‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,20 @@
3030
{{- end }}
3131

3232
{{/*
33-
Gateway reference is NOT inherited from parent. Unlike ingress (where nginx
34-
serves from the publishing namespace and any tenant can attach via the shared
35-
apex), a Gateway's allowedRoutes.namespaces selector is restrictive: a child
36-
tenant namespace is not on the parent Gateway's whitelist, so an HTTPRoute
37-
from the child would be NotAllowedByListeners. The parent Gateway's cert also
38-
only covers <apex> and *.<apex> (one level), and a child apex is
39-
<name>.<parent-apex> — two levels deep — so even if admission let the route
40-
through, TLS would break. Require explicit tenant.spec.gateway=true on each
41-
tenant that wants Gateway-attached apps; otherwise apps fall back to the
42-
inherited Ingress.
33+
Gateway reference is NOT inherited from parent. A child tenant
34+
namespace is not on the parent Gateway's allowedRoutes whitelist,
35+
and the parent Gateway's wildcard cert only covers <apex> +
36+
*.<apex> (one level) while a child apex would be two levels deep —
37+
inheritance would break both admission and TLS. Each tenant that
38+
wants Gateway-attached apps either sets tenant.spec.gateway=true
39+
explicitly or hits the auto-default for derived-apex tenants
40+
(tenant.gatewayEffective). The same helper is consulted by
41+
gateway.yaml (HelmRelease render) so the per-tenant Gateway, the
42+
namespace label, and _namespace.gateway propagation to apps stay
43+
in lockstep.
4344
*/}}
4445
{{- $gateway := "" }}
45-
{{- if .Values.gateway }}
46+
{{- if eq (include "tenant.gatewayEffective" .) "true" }}
4647
{{- $gateway = $tenantName }}
4748
{{- end }}
4849

‎packages/system/cozystack-basics/templates/cozystack-values-secret.yaml‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,23 @@ stringData:
1616
host: {{ index .Values._cluster "root-host" | quote }}
1717
etcd: tenant-root
1818
ingress: tenant-root
19+
{{- /* `gateway` is conditional, the other four `_namespace` keys are
20+
unconditional. The `apps/tenant` chart gates tenant-root via
21+
`ne (include "tenant.name" .) "tenant-root"`, so the namespace.yaml
22+
propagation fix that consumes `tenant.gatewayEffective` never
23+
reaches tenant-root — and the `cozystack-values` Secret rendered
24+
here is the only source of `_namespace.gateway` for tenant-root's
25+
apps (harbor, bucket). Without this, those apps render Ingress
26+
instead of HTTPRoute on a cluster with `_cluster.gateway-enabled`
27+
set, even though the cozystack-controller has materialised the
28+
Gateway. Gate on the platform-level flag so non-Gateway clusters
29+
still see the empty string consumers default to. */ -}}
30+
{{- /* toString normalises both string "true" (cozystack-controller's
31+
wire form) and Helm-set bool true (operators using --set on
32+
the bare key without quoting) to the same comparable value;
33+
raw `eq bool string` fails the Helm template render. */ -}}
34+
{{- if eq (toString (index .Values._cluster "gateway-enabled" | default "false")) "true" }}
35+
gateway: tenant-root
36+
{{- end }}
1937
monitoring: tenant-root
2038
seaweedfs: tenant-root
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
suite: cozystack-values Secret for tenant-root
2+
templates:
3+
- templates/cozystack-values-secret.yaml
4+
5+
release:
6+
name: cozystack-basics
7+
namespace: cozy-system
8+
9+
set:
10+
_cluster:
11+
root-host: example.org
12+
13+
# The `cozystack-values` Secret in tenant-root is the bottom of the
14+
# `_namespace.*` lookup chain for tenant-root's own apps (harbor,
15+
# bucket — both read `_namespace.gateway` to switch between Ingress
16+
# and HTTPRoute). The `apps/tenant` chart gates tenant-root via
17+
# `ne (include "tenant.name" .) "tenant-root"`, so the propagation
18+
# logic that flows `tenant.gatewayEffective` into `_namespace.gateway`
19+
# never reaches tenant-root — this Secret is the only place that
20+
# value gets set for the root tenant.
21+
#
22+
# Four of the five `_namespace.*` keys (`etcd`, `ingress`,
23+
# `monitoring`, `seaweedfs`) are always rendered, because their
24+
# dependent platform apps are always installable in tenant-root.
25+
# `gateway` is conditional on `_cluster.gateway-enabled`: when the
26+
# platform-level flag is false (the default), Gateway is not
27+
# installed, and writing `gateway: tenant-root` would point apps at a
28+
# Gateway that doesn't exist. The fixtures below pin both halves of
29+
# that contract.
30+
tests:
31+
- it: omits _namespace.gateway when _cluster.gateway-enabled is missing (default)
32+
asserts:
33+
- notMatchRegex:
34+
path: stringData["values.yaml"]
35+
pattern: '(?m)^\s+gateway:'
36+
37+
- it: omits _namespace.gateway when _cluster.gateway-enabled is "false"
38+
set:
39+
_cluster:
40+
gateway-enabled: "false"
41+
asserts:
42+
- notMatchRegex:
43+
path: stringData["values.yaml"]
44+
pattern: '(?m)^\s+gateway:'
45+
46+
- it: emits _namespace.gateway=tenant-root when _cluster.gateway-enabled is "true"
47+
set:
48+
_cluster:
49+
gateway-enabled: "true"
50+
asserts:
51+
- matchRegex:
52+
path: stringData["values.yaml"]
53+
pattern: '(?m)^\s+gateway: tenant-root$'
54+
55+
- it: keeps _namespace.{etcd,ingress,monitoring,seaweedfs} unconditional when Gateway is off — regression guard for a refactor that accidentally gates them on the same flag
56+
asserts:
57+
- matchRegex:
58+
path: stringData["values.yaml"]
59+
pattern: '(?m)^\s+etcd: tenant-root$'
60+
- matchRegex:
61+
path: stringData["values.yaml"]
62+
pattern: '(?m)^\s+ingress: tenant-root$'
63+
- matchRegex:
64+
path: stringData["values.yaml"]
65+
pattern: '(?m)^\s+monitoring: tenant-root$'
66+
- matchRegex:
67+
path: stringData["values.yaml"]
68+
pattern: '(?m)^\s+seaweedfs: tenant-root$'
69+
70+
- it: keeps _namespace.{etcd,ingress,monitoring,seaweedfs} unconditional when Gateway is on — same guard, opposite mode
71+
set:
72+
_cluster:
73+
gateway-enabled: "true"
74+
asserts:
75+
- matchRegex:
76+
path: stringData["values.yaml"]
77+
pattern: '(?m)^\s+etcd: tenant-root$'
78+
- matchRegex:
79+
path: stringData["values.yaml"]
80+
pattern: '(?m)^\s+ingress: tenant-root$'
81+
- matchRegex:
82+
path: stringData["values.yaml"]
83+
pattern: '(?m)^\s+monitoring: tenant-root$'
84+
- matchRegex:
85+
path: stringData["values.yaml"]
86+
pattern: '(?m)^\s+seaweedfs: tenant-root$'

0 commit comments

Comments
 (0)