processExtensions validates all entries in o.Extensions against the registry, converts raw decoded values (from YAML or JSON) to typed Extension instances, applies defaults, and calls Validate on each. It is idempotent: already-typed entries are only re-validated.
(o *Overrides)
| 145 | // decoded values (from YAML or JSON) to typed Extension instances, applies defaults, and |
| 146 | // calls Validate on each. It is idempotent: already-typed entries are only re-validated. |
| 147 | func processExtensions(o *Overrides) error { |
| 148 | if len(o.Extensions) == 0 { |
| 149 | return nil |
| 150 | } |
| 151 | |
| 152 | extensionRegistry.RLock() |
| 153 | defer extensionRegistry.RUnlock() |
| 154 | |
| 155 | for key, raw := range o.Extensions { |
| 156 | entry, ok := extensionRegistry.entries[key] |
| 157 | if !ok { |
| 158 | isLegacy := isKnownLegacyOverridesField(key) || isRegisteredExtensionLegacyKey(key) |
| 159 | return &unknownExtensionKeyError{key: key, isLegacy: isLegacy} |
| 160 | } |
| 161 | |
| 162 | // Already a typed Extension (set programmatically or after legacy conversion) |
| 163 | if ext, alreadyTyped := raw.(Extension); alreadyTyped { |
| 164 | if err := ext.Validate(); err != nil { |
| 165 | return &extensionError{fmt.Errorf("extension %q: %w", key, err)} |
| 166 | } |
| 167 | continue |
| 168 | } |
| 169 | |
| 170 | // Create a new instance and apply defaults. |
| 171 | instance := entry.newInstance() |
| 172 | // Per-tenant extension configs have no CLI prefix. |
| 173 | instance.RegisterFlagsAndApplyDefaults("", flag.NewFlagSet("", flag.ContinueOnError)) |
| 174 | |
| 175 | // Decode via JSON round-trip, which also normalizes map[any]any from YAML. |
| 176 | b, err := json.Marshal(normalizeYAMLValue(raw)) |
| 177 | if err != nil { |
| 178 | return &extensionError{fmt.Errorf("extension %q: marshal: %w", key, err)} |
| 179 | } |
| 180 | dec := json.NewDecoder(bytes.NewReader(b)) |
| 181 | dec.DisallowUnknownFields() |
| 182 | |
| 183 | err = dec.Decode(instance) |
| 184 | if err != nil { |
| 185 | return &extensionError{fmt.Errorf("extension %q: unmarshal: %w", key, err)} |
| 186 | } |
| 187 | if err := instance.Validate(); err != nil { |
| 188 | return &extensionError{fmt.Errorf("extension %q: %w", key, err)} |
| 189 | } |
| 190 | |
| 191 | o.Extensions[key] = instance |
| 192 | } |
| 193 | return nil |
| 194 | } |
| 195 | |
| 196 | // processLegacyExtensions converts registered extension flat keys in l.Extensions to typed |
| 197 | // Extension instances, giving LegacyOverrides.Extensions the same semantics as |