diff options
| author | James Elliott <james-d-elliott@users.noreply.github.com> | 2025-02-18 20:38:36 +1100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-18 09:38:36 +0000 |
| commit | a9d1986fa9dec8701ee73b05aa99781f4bbe5f18 (patch) | |
| tree | bbcef1a55483271f43308179d4fd09ef8a894131 /internal/configuration/provider.go | |
| parent | 7ac3c6a4f3945c3c4272bac717addd1ef598b2b9 (diff) | |
feat(configuration): reusable definitions (#8077)
This adds reusable definitions into the mix for the configuration. This replaces the existing networks section for the access_control section and is automatically remapped for users.
Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>
Diffstat (limited to 'internal/configuration/provider.go')
| -rw-r--r-- | internal/configuration/provider.go | 96 |
1 files changed, 88 insertions, 8 deletions
diff --git a/internal/configuration/provider.go b/internal/configuration/provider.go index c4f68260d..77c0b3577 100644 --- a/internal/configuration/provider.go +++ b/internal/configuration/provider.go @@ -2,6 +2,7 @@ package configuration import ( "fmt" + "net" "github.com/go-viper/mapstructure/v2" "github.com/knadh/koanf/v2" @@ -13,21 +14,18 @@ import ( func Load(val *schema.StructValidator, sources ...Source) (keys []string, configuration *schema.Configuration, err error) { configuration = &schema.Configuration{} - keys, err = LoadAdvanced(val, "", configuration, sources...) + keys, err = LoadAdvanced(val, "", configuration, nil, sources...) return keys, configuration, err } // LoadAdvanced is intended to give more flexibility over loading a particular path to a specific interface. -func LoadAdvanced(val *schema.StructValidator, path string, result any, sources ...Source) (keys []string, err error) { +func LoadAdvanced(val *schema.StructValidator, path string, result any, definitions *schema.Definitions, sources ...Source) (keys []string, err error) { if val == nil { return keys, errNoValidator } - ko := koanf.NewWithConf(koanf.Conf{ - Delim: constDelimiter, - StrictMerge: false, - }) + ko := koanf.NewWithConf(koanf.Conf{Delim: constDelimiter, StrictMerge: false}) if err = loadSources(ko, val, sources...); err != nil { return ko.Keys(), err @@ -39,11 +37,88 @@ func LoadAdvanced(val *schema.StructValidator, path string, result any, sources return koanfGetKeys(ko), err } - unmarshal(final, val, path, result) + unmarshal(final, val, path, result, definitions) + + mapDefinitionsResult(val, result) return koanfGetKeys(final), nil } +func LoadDefinitions(val *schema.StructValidator, sources ...Source) (definitions *schema.Definitions, err error) { + ko := koanf.NewWithConf(koanf.Conf{Delim: constDelimiter, StrictMerge: false}) + + if err = loadSources(ko, val, sources...); err != nil { + return nil, err + } + + var final *koanf.Koanf + + if final, err = koanfRemapKeys(val, ko, deprecations, deprecationsMKM); err != nil { + return nil, err + } + + legacy := &legacyDefinitions{} + + c := koanf.UnmarshalConf{ + DecoderConfig: &mapstructure.DecoderConfig{ + DecodeHook: mapstructure.ComposeDecodeHookFunc( + mapstructure.StringToSliceHookFunc(","), + StringToIPNetworksHookFunc(nil), + ), + Metadata: nil, + Result: legacy, + WeaklyTypedInput: true, + }, + } + + if err = final.UnmarshalWithConf("", legacy, c); err != nil { + val.Push(fmt.Errorf("error occurred during unmarshalling definitions configuration: %w", err)) + } + + d := legacy.Definitions + + mapDefinitions(val, legacy.AccessControl.Networks, &d) + + return &d, nil +} + +func mapDefinitionsResult(val *schema.StructValidator, result any) { + if config, ok := result.(*schema.Configuration); ok { + mapDefinitions(val, config.AccessControl.Networks, &config.Definitions) + } +} + +func mapDefinitions(val *schema.StructValidator, networks []schema.AccessControlNetwork, definitions *schema.Definitions) { + if len(networks) == 0 { + return + } + + var ok bool + + if definitions.Network == nil { + definitions.Network = make(map[string][]*net.IPNet, len(networks)) + } + + for _, network := range networks { + if _, ok = definitions.Network[network.Name]; ok { + val.Push(fmt.Errorf("error occurred during unmarshalling definitions configuration: the definition for network with name '%s' exists in both the definitions section and access control section which is not permitted", network.Name)) + + continue + } + + definitions.Network[network.Name] = network.Networks + } +} + +type legacyDefinitions struct { + Definitions schema.Definitions `koanf:"definitions"` + AccessControl legacyAccessControl `koanf:"access_control"` +} + +type legacyAccessControl struct { + Networks []schema.AccessControlNetwork `koanf:"networks"` +} + func mapHasKey(k string, m map[string]any) bool { if _, ok := m[k]; ok { return true @@ -52,7 +127,11 @@ func mapHasKey(k string, m map[string]any) bool { return false } -func unmarshal(ko *koanf.Koanf, val *schema.StructValidator, path string, o any) { +func unmarshal(ko *koanf.Koanf, val *schema.StructValidator, path string, o any, definitions *schema.Definitions) { + if definitions == nil { + definitions = &schema.Definitions{} + } + c := koanf.UnmarshalConf{ DecoderConfig: &mapstructure.DecoderConfig{ DecodeHook: mapstructure.ComposeDecodeHookFunc( @@ -68,6 +147,7 @@ func unmarshal(ko *koanf.Koanf, val *schema.StructValidator, path string, o any) StringToCryptographicKeyHookFunc(), StringToTLSVersionHookFunc(), StringToPasswordDigestHookFunc(), + StringToIPNetworksHookFunc(definitions.Network), ToTimeDurationHookFunc(), ToRefreshIntervalDurationHookFunc(), ), |
