ADR-066: Centralized settings management with pydantic-settings¶
Category: architecture Provenance: guided-ai
Decision¶
Use pydantic-settings for centralized operator configuration instead of scattered os.getenv calls throughout the codebase.
Rationale¶
Scattered os.getenv calls throughout the codebase lead to: (1) Inconsistent parsing and validation, (2) Difficult discovery of available configuration options, (3) Type safety issues, (4) Hard to test with mocked configurations, (5) No central documentation of settings. pydantic-settings provides: (1) Automatic type validation and coercion, (2) Single source of truth for all configuration, (3) Better IDE support with autocomplete, (4) Easy testing with model instances, (5) Built-in documentation through Field descriptions, (6) Support for .env files and multiple sources, (7) Validation errors with clear messages. Trade-off: Minimal - pydantic-settings was already a dependency, just not utilized properly.
Context: The operator had environment variable parsing scattered across operator.py, constants.py, drift_detection_service.py, health.py, leader_election.py, and various other modules. Each location manually parsed strings to bools, ints, and floats with inconsistent default handling. This made it difficult to understand what configuration options existed and how they interacted. Centralizing in a Settings class using pydantic-settings provides validation, type safety, and documentation in one location.
References: - https://docs.pydantic.dev/latest/concepts/pydantic_settings/ - https://github.com/pydantic/pydantic-settings
Agent Instructions¶
When adding new configuration options, add them to the Settings class in src/keycloak_operator/settings.py. Never use os.getenv directly in other modules. Import settings from the settings module instead. All environment variables must be documented in the Settings class with Field descriptions.
Rejected Alternatives¶
Config dataclass¶
Rejected due to lack of validation and env parsing.
python-dotenv + manual parsing¶
Rejected due to lack of type safety.
Custom config class¶
Rejected - reinventing the wheel when pydantic-settings exists.
Keep scattered os.getenv¶
Rejected due to maintainability issues.