Skip to content

config: merge environment variable overrides on top of YAML (issue #119) - #172

Merged
wind-c merged 1 commit into
mainfrom
fix/issue-119-config-env-merge
Sep 6, 2026
Merged

wind-c merged 1 commit into
mainfrom
fix/issue-119-config-env-merge

Conversation

@wind-c

@wind-c wind-c commented Aug 30, 2026 •

Copy link
Copy Markdown
Owner

Implements the configuration merging described in #119.

Problem

comqtt v2 loads configuration only from a YAML file via config.Load. In Kubernetes the pod IP is dynamic and the Raft/bind-addr must be a real address, so operators today rewrite the whole YAML (or a config template) just to override a value at deploy time.

Change

config.Load still loads and unmarshals the YAML file as the baseline, then applies environment-variable overrides on top:

  • Env var naming: COMQTT_ + the dotted yaml path of the field, uppercased with - replaced by _, segments joined by _. For example:

    yaml field env var
    cluster.bind-addr COMQTT_CLUSTER_BIND_ADDR
    mqtt.tcp COMQTT_MQTT_TCP
    redis.options.addr COMQTT_REDIS_OPTIONS_ADDR
    dashboard.secret-file COMQTT_DASHBOARD_SECRET_FILE
  • Structure-aware walk via reflection, so nested blocks (mqtt, cluster, log, dashboard, redis, ...) can be overridden field-by-field without rewriting the file.

  • Supports string, int/uint, and bool fields. Slices/maps (e.g. cluster.members) are not overridable via env vars and keep their YAML value.

  • A value is overridden only when the env var is set; an empty string explicitly clears the YAML value. The YAML baseline is unchanged when no overrides are set.

Docs

Added an "Environment variable overrides" section to the README describing the naming rule and supported types.

Tests

Added config/config_test.go cases covering: baseline load unchanged, env var overriding a file value, env var supplying a value the file omits, empty-string clearing, unset-leaves-untouched, and the issue #119 cluster.bind-addr deploy-time override scenario.

go test ./config/... passes.

Refs: #119

@wind-c
wind-c force-pushed the fix/issue-119-config-env-merge branch 3 times, most recently from e1d1136 to aeef815 Compare September 3, 2026 08:31
YAML is loaded as the baseline, then COMQTT_* environment variables are
applied on top so operators can override scalar values at deploy time
without rewriting the config file (e.g. a dynamic Kubernetes pod IP for
cluster.bind-addr with Hashicorp Raft).

- Env var name: COMQTT_ + dotted yaml path, uppercased, '-' -> '_',
  segments joined by '_' (e.g. cluster.bind-addr -> COMQTT_CLUSTER_BIND_ADDR).
- Structure-aware reflection walk over nested blocks (mqtt, cluster, log,
  dashboard, redis, ...); supports string, int/uint and bool fields.
- Slices/maps are not overridable via env and stay at their YAML value.
- YAML baseline is unchanged when no env overrides are set; an empty string
  explicitly clears a value.

Also:
- Document the naming rule in README and in code comments.
- Tests: baseline load unchanged, env overriding a file value, env supplying
  a missing value, empty-string clearing, unset-leaves-untouched, and the
  issue #119 bind-addr scenario. go test ./config/... passes.

Refs: #119
@wind-c
wind-c force-pushed the fix/issue-119-config-env-merge branch from aeef815 to 0363430 Compare September 3, 2026 08:34
@wind-c
wind-c merged commit 11282b9 into main Sep 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant