Skip to content

Commit 4e1bcdb

Browse files
committed
feat(helm): support gateway config arrays of tables
1 parent f9a90a2 commit 4e1bcdb

4 files changed

Lines changed: 59 additions & 6 deletions

File tree

‎deploy/helm/openshell/templates/_toml.tpl‎

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ field must not require a Helm template change.
9797
{{- end -}}
9898
{{- end -}}
9999

100-
{{/* Render the top-level gatewayConfig map as deterministic TOML tables. */}}
100+
{{/* Render the top-level gatewayConfig map as deterministic TOML tables.
101+
Top-level lists represent TOML arrays of tables and preserve their YAML order. */}}
101102
{{- define "openshell.gatewayConfigToml" -}}
102103
{{- $root := . -}}
103104
{{- $config := deepCopy (.Values.gatewayConfig | default dict) -}}
@@ -276,7 +277,7 @@ owner: server.*. Override any gatewayConfig copies before serializing TOML. */}}
276277
{{- range $tableName := keys $config | sortAlpha -}}
277278
{{- $fields := get $config $tableName -}}
278279
{{- if ne $fields nil -}}
279-
{{- if not (kindIs "map" $fields) -}}
280+
{{- if and (not (kindIs "map" $fields)) (not (kindIs "slice" $fields)) -}}
280281
{{- fail (printf "gatewayConfig table %q must be a map, got %s" $tableName (kindOf $fields)) -}}
281282
{{- end -}}
282283
{{- $header := list -}}
@@ -287,6 +288,7 @@ owner: server.*. Override any gatewayConfig copies before serializing TOML. */}}
287288
{{- end -}}
288289
{{- $header = append $header (include "openshell.toml.key" $segment) -}}
289290
{{- end -}}
291+
{{- if kindIs "map" $fields -}}
290292
{{ printf "[%s]\n" (join "." $header) }}
291293
{{- range $fieldName := keys $fields | sortAlpha }}
292294
{{- $value := get $fields $fieldName -}}
@@ -297,6 +299,23 @@ owner: server.*. Override any gatewayConfig copies before serializing TOML. */}}
297299
{{ printf "%s = %s\n" (include "openshell.toml.key" $fieldName) (include "openshell.toml.value" (list $root $value)) }}
298300
{{- end }}
299301
{{- end }}
302+
{{- else -}}
303+
{{- range $index, $entry := $fields -}}
304+
{{- if not (kindIs "map" $entry) -}}
305+
{{- fail (printf "gatewayConfig array-of-tables %q entry %d must be a map, got %s" $tableName $index (kindOf $entry)) -}}
306+
{{- end -}}
307+
{{ printf "[[%s]]\n" (join "." $header) }}
308+
{{- range $fieldName := keys $entry | sortAlpha }}
309+
{{- $value := get $entry $fieldName -}}
310+
{{- if ne $value nil }}
311+
{{- if eq $fieldName "database_url" -}}
312+
{{- fail "gatewayConfig must not contain database_url; provide database credentials through the chart's Secret-backed OPENSHELL_DB_URL environment variable" -}}
313+
{{- end -}}
314+
{{ printf "%s = %s\n" (include "openshell.toml.key" $fieldName) (include "openshell.toml.value" (list $root $value)) }}
315+
{{- end }}
316+
{{- end }}
317+
{{- end -}}
318+
{{- end -}}
300319
{{- end -}}
301320
{{- end -}}
302321
{{- end -}}

‎deploy/helm/openshell/tests/gateway_config_serializer_test.yaml‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,33 @@ tests:
185185
path: data["gateway.toml"]
186186
pattern: omitted_value
187187

188+
- it: renders top-level lists as ordered TOML arrays of tables
189+
set:
190+
gatewayConfig:
191+
openshell.gateway.interceptors:
192+
- name: governance
193+
grpc_endpoint: http://governance.ns.svc.cluster.local:18081
194+
order: 0
195+
failure_policy: fail_closed
196+
- name: audit
197+
grpc_endpoint: http://audit.ns.svc.cluster.local:18081
198+
order: 1
199+
failure_policy: fail_open
200+
asserts:
201+
- matchRegex:
202+
path: data["gateway.toml"]
203+
pattern: '(?ms)^\[\[openshell\.gateway\.interceptors\]\]\nfailure_policy = "fail_closed"\ngrpc_endpoint = "http://governance\.ns\.svc\.cluster\.local:18081"\nname = "governance"\norder = 0\n\[\[openshell\.gateway\.interceptors\]\]\nfailure_policy = "fail_open"\ngrpc_endpoint = "http://audit\.ns\.svc\.cluster\.local:18081"\nname = "audit"\norder = 1$'
204+
205+
- it: rejects non-map entries in a top-level array of tables
206+
set:
207+
gatewayConfig:
208+
example.entries:
209+
- valid: true
210+
- invalid
211+
asserts:
212+
- failedTemplate:
213+
errorMessage: 'gatewayConfig array-of-tables "example.entries" entry 1 must be a map, got string'
214+
188215
- it: evaluates templates only in string values
189216
set:
190217
gatewayConfig:

‎docs/how-it-works/gateways/configuration.mdx‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,15 @@ copies referenced Secret data into `gateway.toml`.
3636

3737
The serializer has a deterministic YAML-to-TOML contract. YAML `null` fields
3838
are omitted; `null` array members are rejected because TOML has no equivalent.
39-
Strings, booleans, integers, and floats preserve their types. Scalar arrays
40-
become TOML arrays, maps become inline tables, and arrays of maps become arrays
41-
of inline tables. Keys are ordered alphabetically, so equivalent input produces
39+
Strings and booleans retain their TOML types, and numeric values remain TOML
40+
numbers. Helm normalizes YAML numbers before templates run, so it cannot retain
41+
the lexical distinction between an integral float such as `1.0` and an integer
42+
such as `1`; both render as the compact TOML value `1`. Scalar arrays become
43+
TOML arrays, maps become inline tables, and arrays of maps inside a table become
44+
arrays of inline tables. A top-level `gatewayConfig` list instead renders an
45+
ordered TOML array of tables: each list item must be a map and emits one
46+
`[[table]]` block. Keys are ordered alphabetically within each table, while
47+
array-of-tables item order follows the YAML list, so equivalent input produces
4248
the same ConfigMap checksum. Helm `tpl` expressions are evaluated only in
4349
string values, never in keys or YAML structure.
4450

‎docs/kubernetes/migrate-gateway-config.mdx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
Chart schema v2 replaces application-specific Helm values with one non-secret
44
`gatewayConfig` map. Its top-level keys are TOML tables; nested maps are TOML
5-
inline tables. Kubernetes resource references (Secrets, certificates, Services,
5+
inline tables. A top-level YAML list is an ordered TOML array of tables, with
6+
one map per `[[table]]` entry. Kubernetes resource references (Secrets, certificates, Services,
67
and mounts) remain chart values.
78

89
## Upgrade compatibility

0 commit comments

Comments
 (0)