Refactored configuration to make sections less code intensive to add

This commit is contained in:
bwilliams committed 2026-10-09 09:30:15 +01:00
1 parent 8b0cecb51b
commit ff33ef082a
4 files changed
+438 -94

No files matched your search

+17 -43
View File
@@ -18,9 +18,8 @@ package config
import (
"encoding/json"
"errors"
"fmt"
"maps"
"log/slog"
"reflect"
"strings"
@@ -31,65 +30,37 @@ import (
const EnvPrefix string = "JOBSEARCH"
const EtcConfigPath string = "/etc/job-search"
// Each field's cfg tag must match the section's JSCK* constant.
type JobSearchConfig struct {
Logging JobSearchConfigLogging
Logging JobSearchConfigLogging `cfg:"logging"`
}
// Default configuration
// Default configuration, taken from the default struct tags
func LoadDefaultConfig() {
conf := JobSearchConfig{
Logging: defaultConfigLogging(),
var conf JobSearchConfig
if err := applyDefaults(&conf); err != nil {
panic(fmt.Sprintf("config: %v", err))
}
LoadToViper(conf)
}
// Converts configuration to a map
func (conf JobSearchConfig) Map() map[string]any {
confMap := map[string]any{}
confMap["logging"] = conf.Logging.Map()
return confMap
}
func (c JobSearchConfig) Map() map[string]any { return mapOf(c) }
// Converts configuration to a flat dotted format
func (conf JobSearchConfig) Flatten() map[string]any {
confFlat := map[string]any{}
maps.Copy(confFlat, conf.Logging.Flatten())
return confFlat
}
func (c JobSearchConfig) Flatten() map[string]any { return flattenOf("", c) }
// Returns the expected type of a configuration key value
func (c JobSearchConfig) TypeOf(key string) (reflect.Kind, error) {
keyParts := strings.Split(key, ".")
switch keyParts[0] {
case "logging":
return c.Logging.TypeOf(strings.Join(keyParts[1:], "."))
default:
return reflect.Invalid, errors.New("unknown configuration key")
}
return typeOf(c, key)
}
// Returns the expected type of a configuration value
func (c JobSearchConfig) ValueOf(key string) (any, error) {
keyParts := strings.Split(key, ".")
switch keyParts[0] {
case "logging":
return c.Logging.ValueOf(strings.Join(keyParts[1:], "."))
default:
return nil, errors.New("unknown configuration key")
}
return valueOf(c, key)
}
// Returns the expected type of a configuration value
func (c *JobSearchConfig) SetValue(key string, value any) error {
keyParts := strings.Split(key, ".")
switch keyParts[0] {
case "logging":
return c.Logging.SetValue(strings.Join(keyParts[1:], "."), value)
default:
return errors.New("unknown configuration key")
}
return setValue(c, key, value)
}
// Utility method for loading a configuration from Viper
func LoadFromViper(conf *JobSearchConfig) {
keys := viper.AllKeys()
for idx := range keys {
@@ -105,10 +76,13 @@ func LoadFromViper(conf *JobSearchConfig) {
conf.SetValue(key, viper.GetInt(key))
case reflect.Bool:
conf.SetValue(key, viper.GetBool(key))
default:
slog.Error(fmt.Sprintf("unknown key type: %s", keyType))
}
}
}
// Utility method for loading a configuration into Viper as defaults
func LoadToViper(conf JobSearchConfig) {
flatMap := conf.Flatten()
for key := range flatMap {
@@ -121,7 +95,7 @@ func (conf JobSearchConfig) String() string {
var sb strings.Builder
for k, v := range conf.Flatten() {
typ, _ := conf.TypeOf(k)
sb.WriteString(fmt.Sprint(k, " = ", v, " <", typ, ">"))
sb.WriteString(fmt.Sprint(k, " = ", v, " <", typ, ">\n"))
}
return sb.String()
}