Description
Allow the gateway to accept multiple configuration files via a repeatable -config flag (e.g. -config base.toml -config prod.toml), so config can be layered as a complete base file plus thin environment/deployment overlays instead of a single monolithic file. This applies to both gateway binaries — the gateway-controller and the gateway-runtime policy-engine.
Behavior
- The
-config flag becomes repeatable. Files are merged in the order given, with last-wins precedence (a key set in a later file overrides the same key from an earlier file).
- Merge semantics follow koanf: nested tables (maps) deep-merge; list/array values are replaced, not appended. This must be documented so overlays that set list keys (e.g.
enabled_publishers, ignore_path_prefixes) are understood to replace the base list.
- Use koanf
StrictMerge (or WithMergeFunc) so a type-mismatched override across files fails loudly rather than silently.
{{ env }} / {{ file }} interpolation runs once, after all files are merged, so a token declared in the base can be resolved by a later overlay. Secrets stay in interpolation sources, not in the overlay TOMLs.
- At least one
-config file remains required and there is no default config file path: omitting -config, or passing a path that does not exist/parse, must fail fast rather than silently boot on built-in defaults. The flag help text documents the repeatable + last-wins behavior.
Scope
Affected code
gateway/gateway-controller/cmd/controller/main.go — replace the single flag.String("config", ...) with a repeatable flag.Var slice.
gateway/gateway-controller/pkg/config/config.go — LoadConfig loops k.Load(file.Provider(p), toml.Parser()) over all paths in order; interpolate/unmarshal/validate on the merged result.
gateway/gateway-runtime/policy-engine/cmd/policy-engine/main.go — same repeatable flag.Var change; require at least one file.
gateway/gateway-runtime/policy-engine/internal/config/config.go — Load becomes variadic, loops the file loads with a StrictMerge koanf instance, and drops the previous optional-file branch so the loader fails closed instead of silently running on defaults (aligning the loader with the already-required flag).
Version
No response
Related Issue
No response
Description
Allow the gateway to accept multiple configuration files via a repeatable
-configflag (e.g.-config base.toml -config prod.toml), so config can be layered as a complete base file plus thin environment/deployment overlays instead of a single monolithic file. This applies to both gateway binaries — thegateway-controllerand thegateway-runtimepolicy-engine.Behavior
-configflag becomes repeatable. Files are merged in the order given, with last-wins precedence (a key set in a later file overrides the same key from an earlier file).enabled_publishers,ignore_path_prefixes) are understood to replace the base list.StrictMerge(orWithMergeFunc) so a type-mismatched override across files fails loudly rather than silently.{{ env }}/{{ file }}interpolation runs once, after all files are merged, so a token declared in the base can be resolved by a later overlay. Secrets stay in interpolation sources, not in the overlay TOMLs.-configfile remains required and there is no default config file path: omitting-config, or passing a path that does not exist/parse, must fail fast rather than silently boot on built-in defaults. The flag help text documents the repeatable + last-wins behavior.Scope
gateway-controllerand thegateway-runtimepolicy-engine.Affected code
gateway/gateway-controller/cmd/controller/main.go— replace the singleflag.String("config", ...)with a repeatableflag.Varslice.gateway/gateway-controller/pkg/config/config.go—LoadConfigloopsk.Load(file.Provider(p), toml.Parser())over all paths in order; interpolate/unmarshal/validate on the merged result.gateway/gateway-runtime/policy-engine/cmd/policy-engine/main.go— same repeatableflag.Varchange; require at least one file.gateway/gateway-runtime/policy-engine/internal/config/config.go—Loadbecomes variadic, loops the file loads with aStrictMergekoanf instance, and drops the previous optional-file branch so the loader fails closed instead of silently running on defaults (aligning the loader with the already-required flag).Version
No response
Related Issue
No response