work on writing and reading configs

This commit is contained in:
2023-11-02 11:35:10 -07:00
parent 5eb722ff0f
commit 2cfada117b
3 changed files with 148 additions and 28 deletions

159
env.go
View File

@@ -1,50 +1,57 @@
package config package config
import ( import (
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"os" "os"
"strings" "strings"
"sync"
"time" "time"
"github.com/BurntSushi/toml"
"gopkg.in/yaml.v3"
) )
type ConfigType string type configType string
const ( const (
ConfigTypeTOML ConfigType = "toml" ConfigTypeTOML configType = "toml"
ConfigTypeYAML ConfigType = "yaml" ConfigTypeYAML configType = "yaml"
ConfigTypeJSON ConfigType = "json" ConfigTypeJSON configType = "json"
) )
type ConfigMap struct {
Key string
Value any
}
type ConfigManager struct { type ConfigManager struct {
configFileUsed string configFileUsed string
configType ConfigType configType configType
envPrefix string envPrefix string
mapConfig map[string]any mapConfig map[string]ConfigMap
defaultConfig map[string]any defaultConfig map[string]ConfigMap
envConfig map[string]string envConfig map[string]ConfigMap
combinedConfig map[string]ConfigMap
mutex sync.RWMutex
explicitDefaults bool
} }
var ( var ErrConfigFileNotFound = errors.New("config File Not Found")
ErrConfigFileNotFound = errors.New("config File Not Found")
)
func NewConfigManager(automaticEnv bool) *ConfigManager { func NewConfigManager(automaticEnv bool) *ConfigManager {
cm := ConfigManager{} cm := ConfigManager{}
cm.envConfig = make(map[string]string) cm.envConfig = make(map[string]ConfigMap)
cm.mapConfig = make(map[string]any) cm.mapConfig = make(map[string]ConfigMap)
cm.defaultConfig = make(map[string]any) cm.defaultConfig = make(map[string]ConfigMap)
cm.combinedConfig = make(map[string]ConfigMap)
cm.envPrefix = "" cm.envPrefix = ""
envSet := os.Environ() envSet := os.Environ()
for _, env := range envSet { for _, env := range envSet {
kv := strings.Split(env, "=") kv := strings.Split(env, "=")
cm.envConfig[kv[0]] = kv[1] lower := strings.ToLower(kv[0])
lowerKey := strings.ToLower(kv[0]) cm.envConfig[lower] = ConfigMap{Key: kv[0], Value: kv[1]}
if cm.envConfig[lowerKey] == "" {
// if the key is not set, set it as the lower case of the key
// but don't clobber any existing, more specific (already lowercase) value
cm.envConfig[lowerKey] = kv[1]
}
} }
return &cm return &cm
} }
@@ -53,7 +60,59 @@ func (c *ConfigManager) ConfigFileUsed() string {
return c.configFileUsed return c.configFileUsed
} }
func (c *ConfigManager) WriteConfig() { func (c *ConfigManager) UseExplicitDefaults(enable bool) {
c.explicitDefaults = enable
}
func (c *ConfigManager) collapse() {
c.mutex.RLock()
defer c.mutex.RUnlock()
ccm := make(map[string]ConfigMap)
for k, v := range c.defaultConfig {
ccm[k] = v
if _, ok := c.envConfig[k]; ok {
ccm[k] = c.envConfig[k]
}
}
for k, v := range c.mapConfig {
ccm[k] = v
}
c.combinedConfig = ccm
}
func (c *ConfigManager) WriteConfig() error {
c.mutex.RLock()
defer c.mutex.RUnlock()
switch c.configType {
case ConfigTypeTOML:
f, err := os.Create(c.configFileUsed)
if err != nil {
return err
}
defer f.Close()
enc := toml.NewEncoder(f)
err = enc.Encode(c.combinedConfig)
return err
case ConfigTypeYAML:
f, err := os.Create(c.configFileUsed)
if err != nil {
return err
}
defer f.Close()
enc := yaml.NewEncoder(f)
err = enc.Encode(c.combinedConfig)
return err
case ConfigTypeJSON:
f, err := os.Create(c.configFileUsed)
if err != nil {
return err
}
defer f.Close()
enc := json.NewEncoder(f)
return enc.Encode(c.combinedConfig)
default:
return fmt.Errorf("config type %s not supported", c.configType)
}
} }
func (c *ConfigManager) GetBool(key string) bool { func (c *ConfigManager) GetBool(key string) bool {
@@ -88,22 +147,72 @@ func (c *ConfigManager) SetConfigType(configType string) error {
return nil return nil
} }
func (c *ConfigManager) SetDefault(key string, value any) {
}
func (c *ConfigManager) SetEnvPrefix(prefix string) { func (c *ConfigManager) SetEnvPrefix(prefix string) {
c.envPrefix = prefix
} }
func (c *ConfigManager) Set(key string, value any) { func (c *ConfigManager) Set(key string, value any) {
c.mutex.Lock()
defer c.mutex.Unlock()
lower := strings.ToLower(key)
c.mapConfig[lower] = ConfigMap{Key: key, Value: value}
}
func (c *ConfigManager) SetDefault(key string, value any) {
c.mutex.Lock()
defer c.mutex.Unlock()
lower := strings.ToLower(key)
c.defaultConfig[lower] = ConfigMap{Key: key, Value: value}
} }
func (c *ConfigManager) GetIntSlice(key string) []int { func (c *ConfigManager) GetIntSlice(key string) []int {
} }
func (c *ConfigManager) ReadInConfig() error { func (c *ConfigManager) ReadInConfig() error {
c.mutex.Lock()
defer c.mutex.Unlock()
// assume config = map[string]any
confFileData, err := readFile(c.configFileUsed, c.configType)
if err != nil {
return err
}
conf := make(map[string]ConfigMap)
for k, v := range confFileData {
lower := strings.ToLower(k)
conf[lower] = ConfigMap{Key: k, Value: v}
}
c.mapConfig = conf
return nil return nil
} }
func readFile(filename string, fileType configType) (map[string]any, error) {
fileData := make(map[string]any)
switch fileType {
case ConfigTypeTOML:
_, err := toml.DecodeFile(filename, &fileData)
return fileData, err
case ConfigTypeYAML:
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
d := yaml.NewDecoder(f)
err = d.Decode(&fileData)
return fileData, err
case ConfigTypeJSON:
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
err = json.NewDecoder(f).Decode(&fileData)
return fileData, err
default:
return nil, fmt.Errorf("config type %s not supported", fileType)
}
}
func (c *ConfigManager) SetConfigName(name string) { func (c *ConfigManager) SetConfigName(name string) {
} }

5
go.mod
View File

@@ -1,3 +1,8 @@
module github.com/taigrr/jety module github.com/taigrr/jety
go 1.21.3 go 1.21.3
require (
github.com/BurntSushi/toml v1.3.2
gopkg.in/yaml.v3 v3.0.1
)

6
go.sum Normal file
View File

@@ -0,0 +1,6 @@
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=