Skip to content

Read configuration from env into typed options structs - #382

Draft
fwiesel wants to merge 4 commits into
mainfrom
config/envconfig
Draft

fwiesel wants to merge 4 commits into
mainfrom
config/envconfig

Conversation

@fwiesel

@fwiesel fwiesel commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Read operator configuration into module-owned options structs with
kelseyhightower/envconfig.
Each module owns its fields, environment tags, and defaults. The loader
processes each module separately with an empty prefix to retain exact
environment names. An explicitly empty environment value does not restore a
default. New settings require a tagged field and the chart's environment
value, not a central registry or custom value handler.

A separate commit generates optional CLI flags with
sflags. One gflag.ParseTo call registers
the aggregate options. Anonymous shared options retain unprefixed flag names.
Named certificate and eviction members supply their existing prefixes.
The module fields own the desc tags. Environment-derived values become flag
defaults. Scalar precedence is CLI, then environment, then built-in default.

Native trait map format: migration required

Trait concurrency uses plain map[string]int with an exact compatibility
alias. No custom Set(), String(), or Type() methods remain.

  • Environment maps use comma-separated colon entries, for example
    EVICTION_TRAIT_CONCURRENCY='A:1,B:2'.
  • CLI maps use repeated flags, for example
    --eviction-trait-concurrency=A:4 --eviction-trait-concurrency=C:3.
    Each flag overrides one key. Unmentioned environment keys remain.
  • Previous TRAIT=N input fails. A comma-separated CLI map is not supported.
  • An empty environment map supplies no overrides. An empty CLI map value
    returns an error and does not clear the map.
  • Native integers use base 0. 0x10 is 16 and 010 is 8.

Module validation checks final positive limits and non-empty trait names
without surrounding whitespace. Valid final duplicates retain the last
value. Malformed environment input fails before CLI registration.
The resolver retains the default cap, lowest matching limit, and minimum
of one.

The separate chart commit removes six --flag=$(ENV_VAR) arguments and
documents the native environment and CLI encodings. Existing tests retain
their option wiring changes. No new repository tests are added.

Relates to #13.

Layout reduction round (2026-11-01)

Controller-owned options now live in their controller files:

  • eviction options → internal/controller/eviction/controller.go
  • certificate options → internal/controller/node_certificate_controller.go
  • shared settings → internal/controller/hypervisor_controller.go (used by the manager and the Hypervisor controller only)

The separate internal/controller/eviction/options.go, internal/controller/options.go, and internal/config/options.go files no longer exist.

Churn vs PR base (added + deleted lines): 441 → 377.

Future settings: add the field (tag + default) to the owning options struct in its controller file — no central registration. Separate new semantic field groups with a blank line to keep reformatting churn low.

Kubernetes uses the environment as the primary configuration interface.
Module-owned options keep each environment name and default with its
field. kelseyhightower/envconfig fills these structs at startup through
separate module calls. Explicitly empty values do not restore defaults.

Use the native integer map handler instead of a custom trait parser.
Environment maps use comma-separated TRAIT:N entries and base-0 integer
values. Keep validation of final positive limits and trait names with
the eviction module. Keep the resolver's cap and minimum-one guard.

Flag generation and descriptions belong to the later CLI commit.
New settings remain fields with library-owned tags, not registry entries.

Signed-off-by: Fabian Wiesel <fabian.wiesel@sap.com>
The deployment already supplies manager settings through environment
variables. Remove the six duplicated --flag=$(ENV_VAR) arguments so
the chart uses that configuration interface directly.

Explain the native map format where operators configure trait limits.
Environment values use comma-separated TRAIT:N entries. CLI overrides
use repeated flags for individual keys. Document base-0 integers and
the difference between empty environment and empty CLI values.

Signed-off-by: Fabian Wiesel <fabian.wiesel@sap.com>
Operators need to inspect and override settings from the command line.
Register the aggregate options once with sflags. An anonymous shared
member retains the existing unprefixed flags. Named controller members
supply the certificate and eviction prefixes. Descriptions remain on
the module-owned fields, beside their environment tags and defaults.

Use native handlers for maps and slices so new fields need no registry
or custom value methods. Trait maps use repeated TRAIT:N flags for
per-key overrides of environment values. Unmentioned keys remain.
Empty CLI map values are invalid. Environment maps use commas between
TRAIT:N entries. Both handlers use base-0 integers.

Scalar CLI values replace environment-derived defaults. Environment
input must parse before CLI registration. Final domain validation stays
with each module. This preserves CLI, environment, and built-in default
precedence without a custom map parser or rendering method.

Signed-off-by: Fabian Wiesel <fabian.wiesel@sap.com>
Settings now live next to their owning controllers, so adding a setting touches one file per controller plus the chart.

Signed-off-by: Fabian Wiesel <fabian.wiesel@sap.com>
@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown

Merging this branch will decrease overall coverage

Impacted Packages Coverage Δ 🤖
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller 73.42% (-1.35%) 👎
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/eviction 65.07% (-2.80%) 👎
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/global 0.00% (-100.00%) 💀 💀 💀 💀 💀
Coverage details

Compared to commit f5172c4 (run #41086905849)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/cobaltcore-dev/openstack-hypervisor-operator/cmd/main.go 0.00% (ø) 0 0 0
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/eviction/controller.go 65.07% (-2.80%) 209 (+16) 136 (+5) 73 (+11) 👎
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/hypervisor_controller.go 73.28% (-6.72%) 131 (+11) 96 35 (+11) 👎
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/node_certificate_controller.go 72.34% (-8.61%) 47 (+5) 34 13 (+5) 👎
github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/global/global.go 0.00% (-100.00%) 0 (-7) 0 (-7) 0 💀 💀 💀 💀 💀

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files:

  • github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/eviction/controller_test.go
  • github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/controller/hypervisor_controller_test.go
  • github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/global/global_test.go

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