diff --git a/config/config.go b/config/config.go index 0b75fe5cbc1..02a93b7f8a8 100644 --- a/config/config.go +++ b/config/config.go @@ -119,9 +119,7 @@ func FromMap(v map[string]interface{}) (*Config, error) { return nil, err } var conf Config - decoder := json.NewDecoder(buf) - decoder.DisallowUnknownFields() - if err := decoder.Decode(&conf); err != nil { + if err := json.NewDecoder(buf).Decode(&conf); err != nil { return nil, fmt.Errorf("failure to decode config: %w", err) } return &conf, nil @@ -154,3 +152,36 @@ func (c *Config) Clone() (*Config, error) { return &newConfig, nil } + +// Check if the provided key is present in the structure. +func CheckKey(key string) error { + confmap, err := ToMap(&Config{}) + if err != nil { + return err + } + var ok bool + var mcursor map[string]interface{} + var cursor interface{} = confmap + + parts := strings.Split(key, ".") + for i, part := range parts { + sofar := strings.Join(parts[:i], ".") + + mcursor, ok = cursor.(map[string]interface{}) + if !ok { + return fmt.Errorf("%s key is not a map", sofar) + } + + cursor, ok = mcursor[part] + if !ok { + // Construct the current path traversed to print a nice error message + var path string + if len(sofar) > 0 { + path += sofar + "." + } + path += part + return fmt.Errorf("%s not found", path) + } + } + return nil +} diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index b21b555cf7d..e7577f9dc19 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -676,6 +676,12 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error { return errors.New("repo is closed") } + // Validate the key's presence in the config structure. + err := config.CheckKey(key) + if err != nil { + return err + } + // Load into a map so we don't end up writing any additional defaults to the config file. var mapconf map[string]interface{} if err := serialize.ReadConfigFile(r.configFilePath, &mapconf); err != nil {