config updated to improve setting values, writing changes and test coverage
This commit is contained in:
1 parent
8f0e72821f
commit
169c6c6b64
8 files changed
+453
-59
No files matched your search
+72
-40
@@ -10,74 +10,106 @@ import (
|
||||
)
|
||||
|
||||
// StoreValue parses value as the type of key, checks conf accepts it, sets it
|
||||
// in conf and Viper and writes the config file Viper is using. It returns the
|
||||
// parsed value and its kind.
|
||||
// in conf and Viper and writes it to the config file Viper is using. Only the
|
||||
// file's own settings are written back, not defaults or environment
|
||||
// variables. It returns the stored value (as ValueOf gives it) and its kind.
|
||||
func StoreValue(
|
||||
conf *JobSearchConfig, key string, value string,
|
||||
) (any, reflect.Kind, error) {
|
||||
var confValue any = nil
|
||||
var confType reflect.Kind
|
||||
var err error
|
||||
return storeValue(conf, key, value)
|
||||
}
|
||||
|
||||
confType, err = conf.TypeOf(key)
|
||||
// storeValue is StoreValue for any section, so key types that
|
||||
// JobSearchConfig doesn't have yet can be tested.
|
||||
func storeValue(s Section, key string, value string) (any, reflect.Kind, error) {
|
||||
confType, err := s.TypeOf(key)
|
||||
if err != nil {
|
||||
return nil, confType, err
|
||||
}
|
||||
|
||||
switch confType {
|
||||
case reflect.Bool:
|
||||
confValue, err = strconv.ParseBool(value)
|
||||
case reflect.String:
|
||||
confValue = value
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
confValue, err = strconv.ParseInt(value, 10, 64)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
confValue, err = strconv.ParseUint(value, 10, 64)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
confValue, err = strconv.ParseFloat(value, 64)
|
||||
default:
|
||||
err = errors.ErrUnsupported
|
||||
}
|
||||
if err != nil {
|
||||
// Check the value is of the right kind first, for a clearer error than
|
||||
// SetValue gives.
|
||||
if _, err := parseValue(confType, value); err != nil {
|
||||
return nil, confType, fmt.Errorf(
|
||||
"config value type not accepted, expected <%s>", confType,
|
||||
)
|
||||
}
|
||||
|
||||
// Reject values the configuration itself would not accept, e.g. an
|
||||
// unknown log level or an unparseable duration.
|
||||
if err := conf.SetValue(key, confValue); err != nil {
|
||||
// SetValue parses the string into the field's own type (e.g. int8,
|
||||
// float32 or time.Duration) and rejects values the configuration itself
|
||||
// would not accept, e.g. an unknown log level or an unparseable duration.
|
||||
if err := s.SetValue(key, value); err != nil {
|
||||
return nil, confType, err
|
||||
}
|
||||
confValue, err := s.ValueOf(key)
|
||||
if err != nil {
|
||||
return nil, confType, err
|
||||
}
|
||||
|
||||
viper.Set(key, confValue)
|
||||
if err := viper.WriteConfig(); err != nil {
|
||||
file, err := readUsedConfigFile()
|
||||
if err != nil {
|
||||
return nil, confType, err
|
||||
}
|
||||
file.Set(key, confValue)
|
||||
if err := file.WriteConfig(); err != nil {
|
||||
return nil, confType, err
|
||||
}
|
||||
|
||||
return confValue, confType, nil
|
||||
}
|
||||
|
||||
// PurgeValue rewrites the config file Viper is using without key.
|
||||
// parseValue parses value as a value of kind, returning
|
||||
// errors.ErrUnsupported for a kind it can't parse.
|
||||
func parseValue(kind reflect.Kind, value string) (any, error) {
|
||||
switch kind {
|
||||
case reflect.Bool:
|
||||
return strconv.ParseBool(value)
|
||||
case reflect.String:
|
||||
return value, nil
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return strconv.ParseInt(value, 10, 64)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return strconv.ParseUint(value, 10, 64)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return strconv.ParseFloat(value, 64)
|
||||
}
|
||||
return nil, errors.ErrUnsupported
|
||||
}
|
||||
|
||||
// PurgeValue rewrites the config file Viper is using without key. The
|
||||
// file's other settings are kept as they are; defaults and environment
|
||||
// variables are not written to it.
|
||||
func PurgeValue(conf *JobSearchConfig, key string) error {
|
||||
if _, err := conf.TypeOf(key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v := viper.New()
|
||||
v.SetConfigFile(viper.ConfigFileUsed())
|
||||
|
||||
keys := viper.AllKeys()
|
||||
for i := range keys {
|
||||
k := keys[i]
|
||||
if k != key {
|
||||
v.Set(k, viper.Get(k))
|
||||
}
|
||||
}
|
||||
|
||||
if err := v.WriteConfig(); err != nil {
|
||||
file, err := readUsedConfigFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
out := viper.New()
|
||||
out.SetConfigFile(file.ConfigFileUsed())
|
||||
for _, k := range file.AllKeys() {
|
||||
if k != key {
|
||||
out.Set(k, file.Get(k))
|
||||
}
|
||||
}
|
||||
return out.WriteConfig()
|
||||
}
|
||||
|
||||
// readUsedConfigFile reads the config file Viper is using into a new Viper, so
|
||||
// it holds only the file's settings.
|
||||
func readUsedConfigFile() (*viper.Viper, error) {
|
||||
path := viper.ConfigFileUsed()
|
||||
if path == "" {
|
||||
return nil, errors.New("no configuration file in use")
|
||||
}
|
||||
file := viper.New()
|
||||
file.SetConfigFile(path)
|
||||
if err := file.ReadInConfig(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
Reference in new issue
Block a user