Documentation
¶
Index ¶
- Constants
- func AddSource[T any](c *Configuration, src Source[T]) error
- func Get[T any](c *Configuration, name string) (T, bool)
- func LogArgs(cfg any) []any
- func Lookup[T any](c *Configuration, name string) (T, error)
- func MustGet[T any](c *Configuration, name string) T
- func SecretPresence(cfg any) []any
- type Configuration
- func (c *Configuration) AddSourceValue(src cf.ConfigSourceValue) error
- func (c *Configuration) GetDependencies() []string
- func (c *Configuration) GetInitOrderStage() cf.Stage
- func (c *Configuration) Init(ctx context.Context, fw *cf.CaerusFramework) error
- func (c *Configuration) JobRequests() ([]cf.JobRequest, error)
- func (c *Configuration) MetricSamples() []MetricSample
- func (c *Configuration) Name() string
- func (c *Configuration) ParseFlags(args []string) (rest []string, err error)
- func (c *Configuration) Reload(name string) error
- func (c *Configuration) ReloadAll() error
- func (c *Configuration) ResetFlags()
- func (c *Configuration) Shutdown(ctx context.Context) error
- func (c *Configuration) Sources() []string
- type FieldError
- type Format
- type MetricSample
- type Option
- type Source
Constants ¶
const ( // SecretTag is the struct-tag key. SecretTag = "secret" // SecretRedact is the only supported tag value: print [redacted] / presence, // never the cleartext, when using LogArgs / SecretPresence. SecretRedact = "redact" )
Secret tag convention (this module owns the name; logs owns the appearance).
Password string `json:"password" env:"PASSWORD" secret:"redact"`
Overlay, Get, and Lookup are unchanged: the live value still holds the password. Only helpers in this file look at the tag, for logs and tests.
const ComponentName = "configuration"
ComponentName is the framework component name for the configuration component. It is the identifier other components use in GetDependencies to require configuration.
const MaxConfigFileBytes int64 = 1 << 20
MaxConfigFileBytes is the largest configuration file this component will read (1 MiB). That matches the Kubernetes ConfigMap/Secret object size. Typed chassis configs are far smaller; a bigger file usually means the process was pointed at the wrong path. The bound is on-disk size before decode — it does not cap YAML expansion in memory (prefer JSON in production).
Variables ¶
This section is empty.
Functions ¶
func AddSource ¶
func AddSource[T any](c *Configuration, src Source[T]) error
AddSource registers and loads a configuration source on the given component. The value is built immediately (fail-fast); the source is not registered on failure. Reloads never fail the process: a rejected reload keeps the previous value. AddSource is safe to call before or after Init.
Path and/or EnvPrefix must be set. Format is required when Path is set.
func Get ¶
func Get[T any](c *Configuration, name string) (T, bool)
Get returns a snapshot copy of the current value of the named source, typed as T. It reports false if the source does not exist or was registered with a different type. Returning by value means the caller owns a stable copy: it cannot accidentally mutate the live config, and the value does not go stale when a reload swaps the internal pointer.
func LogArgs ¶ added in v0.0.8
LogArgs returns slog key/value pairs for a config struct (or pointer). Top-level exported fields only (same limit as env/flag overlay).
- Unmarked scalars stay visible (host, port, …).
- Fields tagged `secret:"redact"` become RedactedString plus `<json>_set`.
- Nested structs are skipped. Do not slog.Any the raw struct instead.
func Lookup ¶
func Lookup[T any](c *Configuration, name string) (T, error)
Lookup returns a snapshot copy of the current value of the named source, typed as T, or an error if it does not exist or was registered with a different type. Prefer Lookup (or Get) from Init and OnConfigReload so misconfiguration surfaces as error rather than panic.
func MustGet ¶
func MustGet[T any](c *Configuration, name string) T
MustGet returns a snapshot copy of the current value of the named source, typed as T, or panics if it does not exist or was registered with a different type. Prefer Lookup in Init/reload; MustGet is crash-fast sugar for main and tests where a missing source is a programmer error.
func SecretPresence ¶ added in v0.0.8
SecretPresence returns only `<json>_set` bools for `secret:"redact"` string fields. Use on reload summaries when you already log host/port yourself.
Types ¶
type Configuration ¶
type Configuration struct {
// contains filtered or unexported fields
}
Configuration is the caerus-framework-configuration component. It owns a set of per-component configuration sources: each is loaded exactly once, watched for changes, and swapped atomically on a validated reload.
func New ¶
func New(opts ...Option) *Configuration
New creates a configuration component. Add sources with AddSource (from any component's Init) and read the current value with Get/MustGet.
func (*Configuration) AddSourceValue ¶
func (c *Configuration) AddSourceValue(src cf.ConfigSourceValue) error
AddSourceValue registers a configuration source from its generic-free declaration (cf.ConfigSourceValue). It is the cycle-free entry point for core modules (logs, observability) that the configuration module imports: the framework hands them the component as cf.ConfigSourceAdder and they call this with their own declaration. Sample's dynamic type selects the concrete config struct and decoding, exactly as Source[T].T would.
func (*Configuration) GetDependencies ¶
func (c *Configuration) GetDependencies() []string
GetDependencies implements cf.Dependencies. The component logs through the framework logs component.
func (*Configuration) GetInitOrderStage ¶
func (c *Configuration) GetInitOrderStage() cf.Stage
GetInitOrderStage implements cf.CaerusComponent. Configuration runs in the second bootstrap stage, right after logs, so later components can read their config during Init.
func (*Configuration) Init ¶
func (c *Configuration) Init(ctx context.Context, fw *cf.CaerusFramework) error
Init implements cf.CaerusComponent. It starts the file watcher and the reload loop, and begins watching every source registered so far. Sources registered later (during other components' Init) are watched immediately.
After starting the watcher it notifies each source's owner with the already-loaded value. The core components initialize before configuration (logs) or without a Lookup path (logs again) — the initial notification is how they receive their configuration after booting on defaults.
func (*Configuration) JobRequests ¶
func (c *Configuration) JobRequests() ([]cf.JobRequest, error)
JobRequests implements cf.JobSource. It inspects every registered source's declared job flag (the flag must have been parsed by ParseFlags) and reports the requested jobs: the flag names the instance (the source's Owner), the value names the task to run on it (e.g. --postgresql.job=migrate → run task "migrate" on the "postgresql" instance). A task outside the source's declared Tasks set is an error. Two flags that name the same Owner are an error: one job per target per process. CLI-only: file and environment values never produce a job request. Empty (no job flag provided) returns an empty slice.
JobRequests must run after argv absorption; the framework calls it before any component initializes. Sources are visited in registration order so a duplicate-Owner error names a stable pair of flags.
func (*Configuration) MetricSamples ¶ added in v0.0.14
func (c *Configuration) MetricSamples() []MetricSample
MetricSamples returns the configuration_info sample when at least one source is registered. Returns nil before any source is registered (lazy pickup on /metrics).
func (*Configuration) Name ¶
func (c *Configuration) Name() string
Name implements cf.CaerusComponent.
func (*Configuration) ParseFlags ¶
func (c *Configuration) ParseFlags(args []string) (rest []string, err error)
ParseFlags registers --<flag> for every currently registered source's flag-tagged fields and a --<source-name> file-path flag for every source with a Path, parses args, and re-applies the resulting values across all sources (flags win over env; env wins over file). The file-path flags override where each source's config file is read from; defaults are the sources' current paths, so an absent flag is a no-op.
Flags are a process-start overlay: the parsed field map is kept and re-applied on every subsequent Reload / ReloadAll; a path override persists on the source itself (reloads and the file watcher follow it).
Register all AddSource calls first so the flag definitions exist. Unknown flags and positional args are returned untouched — subcommands (`serve`, `migrate`) and app flags fall through to the caller.
func (*Configuration) Reload ¶
func (c *Configuration) Reload(name string) error
Reload forces a re-load of the named source, reapplying env overlay and AfterLoad even when the file bytes are unchanged. Use this after an external process env change (for example from a SIGHUP handler). The process environment is not watchable; without Reload (or a file change), new env values are invisible. Returns an error if the source is unknown or the load is rejected (previous value kept). Notifies the owner on success when the effective value changed.
func (*Configuration) ReloadAll ¶
func (c *Configuration) ReloadAll() error
ReloadAll forces Reload on every registered source. Owners are notified after all loads complete. The first load error is returned; later sources still run.
func (*Configuration) ResetFlags ¶ added in v0.0.14
func (c *Configuration) ResetFlags()
ResetFlags clears the process-start flag overlay. It is for tests only — production binaries call ParseFlags once at process start and never reset.
func (*Configuration) Shutdown ¶
func (c *Configuration) Shutdown(ctx context.Context) error
Shutdown implements cf.CaerusComponent. It stops the watcher and waits for the reload loop to exit. Safe to call even if Init never ran.
func (*Configuration) Sources ¶
func (c *Configuration) Sources() []string
Sources returns the names of registered configuration sources in sorted order. Returns nil when no sources are registered.
type FieldError ¶ added in v0.0.14
FieldError attaches a configuration field name to a validation failure. Return it from Source.Validate so AddSource and reload errors name the field and constraint:
if cfg.MaxConns < 1 {
return &FieldError{Field: "max_conns", Err: errors.New("must be >= 1")}
}
func (*FieldError) Error ¶ added in v0.0.14
func (e *FieldError) Error() string
func (*FieldError) Unwrap ¶ added in v0.0.14
func (e *FieldError) Unwrap() error
type MetricSample ¶ added in v0.0.14
MetricSample is one bootstrap metric sample for observability to scrape. Configuration does not implement cf_observability.MetricsProvider — that would create an import cycle — so observability registers an internal collector that calls MetricSamples.
type Option ¶
type Option func(*options)
Option configures the configuration component at construction time.
func WithLogger ¶
WithLogger overrides the logger used for reload/watcher diagnostics. By default the component logs through the framework logs component (declared in GetDependencies); WithLogger is an explicit override for tests and embedded use and wins over the framework logger. slog.Default() remains the fallback only when neither is available.
type Source ¶
type Source[T any] struct { // Name is the logical name of this source (e.g. "mongodb"). It is the key // used by Get/MustGet and must be unique within the framework. Name string // Path is the configuration file path. It may be a symlink (as with // Kubernetes ConfigMap/Secret mounts), so the directory is watched and the // target is re-stat'ed on every event; see docs/K8S.md. Empty is allowed // when EnvPrefix is set (fileless / env-only source). // // A source with a Path also gets a --<Name> file-path flag in ParseFlags: // providing it overrides where the file is read from (defaults to this // Path). There is no "config directory" bootstrap setting — each source // declares its own file, env and arg options. // // Path is trusted: the process opens any file that uid can read. There is // no directory allowlist. The --<Name> override is the same trust (argv / // Pod spec), not a sandbox. filepath.Abs is not a jail. Path string // Format selects the file encoding. Ignored when Path is empty. Format Format // Owner is the Name of the component that consumes this configuration. On a // validated reload, the owner's OnConfigReload (if it implements // cf.ConfigReloader) is invoked. Empty disables reload dispatch. Owner string // EnvPrefix, when non-empty, overlays matching environment variables onto // the decoded value after the file is read (or onto a zero value when Path // is empty). Keys are EnvPrefix + `env` tag, or UPPER_SNAKE of the json // name. Example: EnvPrefix "POSTGRES_" and field `Host` → POSTGRES_HOST. EnvPrefix string // Job, when declared, registers a CLI-only job flag for this source's Owner. // The flag names the instance and the value names the task to run on it // (e.g. --postgresql.job=migrate); the framework reads the request via // cf.JobSource after argv absorption and routes it before serving. CLI-only: // the value lives in the parsed flag, never in the config file or // environment. Tasks lists allowed task strings and is required when Flag // is set (Flag without Tasks fails at AddSource). A value outside Tasks // fails JobRequests. Two sources must not set a // job flag for the same Owner in one process (JobRequests fails closed: // one job per target). The source must set Owner. Job cf.JobSpec // AfterLoad runs after file+env overlay and before Validate. Use it for // DSN/URL overlays (e.g. POSTGRES_DSN → OverlayDSN). Nil skips the step. AfterLoad func(*T) error // Validate runs after every successful load (initial and reload). It must // return nil for the new value to be accepted. On reload, a rejected value // keeps the previous one in effect. Validate func(*T) error }
Source describes one configuration source and how to interpret it. It is generic over the concrete config type, so each component gets its own strongly-typed config with no shared global struct.
Load order (later wins): file (if Path set) → env overlay (if EnvPrefix set) → flag overlay (if ParseFlags ran and the struct has flag tags) → AfterLoad → Validate. Files are the Kubernetes rotation plane (External Secrets → mount → fsnotify); env is for local/CI/PaaS; flags are a process-start overlay and do not hot-reload by themselves.