(unmarshal func(interface{}) error)
| 315 | } |
| 316 | |
| 317 | func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { |
| 318 | // Note: this implementation relies on callers using yaml.UnmarshalStrict. In non-strict mode |
| 319 | // unmarshal() will not return an error for legacy configuration and we return immediately. |
| 320 | |
| 321 | // Try to unmarshal it normally. Overrides.UnmarshalYAML calls processExtensions for c.Defaults. |
| 322 | // If the error is an extensionError, the config is in the new format but misconfigured. |
| 323 | type rawConfig Config |
| 324 | err := unmarshal((*rawConfig)(c)) |
| 325 | if err == nil { |
| 326 | c.ConfigType = ConfigTypeNew |
| 327 | return nil |
| 328 | } |
| 329 | |
| 330 | // Fail only on extension-specific errors, otherwise fallback to legacy mode |
| 331 | if isExtensionError(err) || isExtensionKeyError(err) { |
| 332 | return err |
| 333 | } |
| 334 | |
| 335 | // Try to unmarshal inline limits |
| 336 | type legacyConfig struct { |
| 337 | DefaultOverrides LegacyOverrides `yaml:",inline"` |
| 338 | |
| 339 | PerTenantOverrideConfig string `yaml:"per_tenant_override_config"` |
| 340 | PerTenantOverridePeriod model.Duration `yaml:"per_tenant_override_period"` |
| 341 | |
| 342 | UserConfigurableOverridesConfig UserConfigurableOverridesConfig `yaml:"user_configurable_overrides"` |
| 343 | |
| 344 | EnableLegacyOverrides bool `yaml:"enable_legacy_overrides"` |
| 345 | } |
| 346 | var legacyCfg legacyConfig |
| 347 | legacyCfg.DefaultOverrides = c.Defaults.toLegacy() |
| 348 | legacyCfg.PerTenantOverrideConfig = c.PerTenantOverrideConfig |
| 349 | legacyCfg.PerTenantOverridePeriod = c.PerTenantOverridePeriod |
| 350 | legacyCfg.UserConfigurableOverridesConfig = c.UserConfigurableOverridesConfig |
| 351 | legacyCfg.EnableLegacyOverrides = c.EnableLegacyOverrides |
| 352 | |
| 353 | if legacyErr := unmarshal(&legacyCfg); legacyErr != nil { |
| 354 | return fmt.Errorf("failed to unmarshal config: %w; also failed in legacy format: %w", err, legacyErr) |
| 355 | } |
| 356 | |
| 357 | // Ensure legacy extension flat keys are converted to typed instances before toNewLimits. |
| 358 | // processLegacyExtensions may not be triggered automatically for inline struct fields. |
| 359 | if err := processLegacyExtensions(&legacyCfg.DefaultOverrides); err != nil { |
| 360 | return fmt.Errorf("defaults: %w", err) |
| 361 | } |
| 362 | |
| 363 | c.Defaults = *legacyCfg.DefaultOverrides.toNewLimits() |
| 364 | c.PerTenantOverrideConfig = legacyCfg.PerTenantOverrideConfig |
| 365 | c.PerTenantOverridePeriod = legacyCfg.PerTenantOverridePeriod |
| 366 | c.UserConfigurableOverridesConfig = legacyCfg.UserConfigurableOverridesConfig |
| 367 | c.EnableLegacyOverrides = legacyCfg.EnableLegacyOverrides |
| 368 | c.ConfigType = ConfigTypeLegacy |
| 369 | return nil |
| 370 | } |
| 371 | |
| 372 | // RegisterFlagsAndApplyDefaults adds the flags required to config this to the given FlagSet |
| 373 | func (c *Config) RegisterFlagsAndApplyDefaults(f *flag.FlagSet) { |
nothing calls this directly
no test coverage detected