Migrate to go.akpain.net/cfger from homebrew configuration loader
This commit is contained in:
parent
279a90327d
commit
af6bb96c4d
4 changed files with 29 additions and 141 deletions
17
go.mod
17
go.mod
|
@ -3,15 +3,10 @@ module github.com/codemicro/palmatum
|
|||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rs/zerolog v1.30.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/julienschmidt/httprouter v1.3.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
github.com/jmoiron/sqlx v1.4.0
|
||||
github.com/julienschmidt/httprouter v1.3.0
|
||||
github.com/mattn/go-sqlite3 v1.14.24
|
||||
go.akpain.net/cfger v0.2.1
|
||||
golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
|
30
go.sum
30
go.sum
|
@ -1,23 +1,21 @@
|
|||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
|
||||
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
|
||||
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c=
|
||||
github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
go.akpain.net/cfger v0.2.1 h1:EXbJqxIAJWuYvYX/HqaG85u2Ikk2Xs1foLTUsnIz7bQ=
|
||||
go.akpain.net/cfger v0.2.1/go.mod h1:uaeo30IdnyNNBIEAT0SwvGIWGBauxMI+THVbk8L0oTs=
|
||||
golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b h1:r+vk0EmXNmekl0S0BascoeeoHk/L7wmaW2QF90K+kYI=
|
||||
golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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=
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"go.akpain.net/cfger"
|
||||
"golang.org/x/exp/slog"
|
||||
)
|
||||
|
||||
|
@ -26,23 +27,23 @@ type Config struct {
|
|||
}
|
||||
|
||||
func Load() (*Config, error) {
|
||||
cl := new(configLoader)
|
||||
if err := cl.load("config.yml"); err != nil {
|
||||
cl := new(cfger.ConfigLoader)
|
||||
if err := cl.Load("config.yml"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conf := &Config{
|
||||
Debug: asBool(cl.withDefault("debug", false)),
|
||||
Debug: cl.Get("debug").WithDefault(false).AsBool(),
|
||||
HTTP: &HTTP{
|
||||
Host: asString(cl.withDefault("http.host", "127.0.0.1")),
|
||||
Port: asInt(cl.withDefault("http.port", 8080)),
|
||||
Host: cl.Get("http.host").WithDefault("127.0.0.1").AsString(),
|
||||
Port: cl.Get("http.port").WithDefault(8080).AsInt(),
|
||||
},
|
||||
Database: &Database{
|
||||
DSN: asString(cl.withDefault("database.dsn", "website.db")),
|
||||
DSN: cl.Get("database.dsn").WithDefault("palmatum.db").AsString(),
|
||||
},
|
||||
Platform: &Platform{
|
||||
SitesDirectory: asString(cl.required("platform.sitesDirectory")),
|
||||
MaxUploadSizeMegabytes: asInt(cl.withDefault("platform.maxUploadSizeMegabytes", 512)),
|
||||
SitesDirectory: cl.Get("platform.sitesDirectory").Required().AsString(),
|
||||
MaxUploadSizeMegabytes: cl.Get("platform.maxUploadSizeMegabytes").WithDefault(512).AsInt(),
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"golang.org/x/exp/slog"
|
||||
"gopkg.in/yaml.v3"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type configLoader struct {
|
||||
rawConfigFileContents map[string]any
|
||||
lastKey string
|
||||
}
|
||||
|
||||
func (cl *configLoader) load(fname string) error {
|
||||
cl.rawConfigFileContents = make(map[string]any)
|
||||
fcont, err := os.ReadFile(fname)
|
||||
if err != nil {
|
||||
slog.Warn("cannot load config file", "filename", fname)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := yaml.Unmarshal(fcont, &cl.rawConfigFileContents); err != nil {
|
||||
return fmt.Errorf("unmarshaling config file: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type optionalItem struct {
|
||||
item any
|
||||
found bool
|
||||
}
|
||||
|
||||
var indexedPartRegexp = regexp.MustCompile(`(?m)([a-zA-Z]+)(?:\[(\d+)\])?`)
|
||||
|
||||
func (cl *configLoader) get(key string) optionalItem {
|
||||
// httpcore[2].bananas
|
||||
cl.lastKey = key
|
||||
|
||||
parts := strings.Split(key, ".")
|
||||
var cursor any = cl.rawConfigFileContents
|
||||
for _, part := range parts {
|
||||
components := indexedPartRegexp.FindStringSubmatch(part)
|
||||
key := components[1]
|
||||
index, _ := strconv.ParseInt(components[2], 10, 32)
|
||||
isIndexed := components[2] != ""
|
||||
|
||||
item, found := cursor.(map[string]any)[key]
|
||||
if !found {
|
||||
return optionalItem{nil, false}
|
||||
}
|
||||
|
||||
if isIndexed {
|
||||
arr, conversionOk := item.([]any)
|
||||
if !conversionOk {
|
||||
slog.Error(fmt.Sprintf("attempted to index non-indexable config item %s", key))
|
||||
os.Exit(1)
|
||||
}
|
||||
cursor = arr[index]
|
||||
} else {
|
||||
cursor = item
|
||||
}
|
||||
}
|
||||
return optionalItem{cursor, true}
|
||||
}
|
||||
|
||||
func (cl *configLoader) required(key string) optionalItem {
|
||||
opt := cl.get(key)
|
||||
if !opt.found {
|
||||
slog.Error(fmt.Sprintf("required key %s not found in config file", key))
|
||||
os.Exit(1)
|
||||
}
|
||||
return opt
|
||||
}
|
||||
|
||||
func (cl *configLoader) withDefault(key string, defaultValue any) optionalItem {
|
||||
opt := cl.get(key)
|
||||
if !opt.found {
|
||||
return optionalItem{item: defaultValue, found: true}
|
||||
}
|
||||
return opt
|
||||
}
|
||||
|
||||
func asInt(x optionalItem) int {
|
||||
if !x.found {
|
||||
return 0
|
||||
}
|
||||
return x.item.(int)
|
||||
}
|
||||
|
||||
func asString(x optionalItem) string {
|
||||
if !x.found {
|
||||
return ""
|
||||
}
|
||||
return x.item.(string)
|
||||
}
|
||||
|
||||
func asBool(x optionalItem) bool {
|
||||
if !x.found {
|
||||
return false
|
||||
}
|
||||
return x.item.(bool)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue