88 lines
2.3 KiB
Go
88 lines
2.3 KiB
Go
// Run with go run ./examples/configuration -format xml, or -config /path/to/app.yaml.
|
|
package main
|
|
|
|
import (
|
|
"embed"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"git.yuntuo.hk/k2safe/go-omni/config"
|
|
)
|
|
|
|
//go:embed config.json config.yaml config.xml
|
|
var examples embed.FS
|
|
|
|
type ClientConfig struct {
|
|
Endpoint string `json:"endpoint"`
|
|
Timeout time.Duration `json:"timeout"`
|
|
// The file chooses a fixed value or an explicit environment reference.
|
|
Token string `json:"token"`
|
|
}
|
|
type Config struct {
|
|
Client ClientConfig `json:"client"`
|
|
MaxItems int `json:"maxItems"`
|
|
Allowed []string `json:"allowed"`
|
|
}
|
|
|
|
func Default() Config { return Config{Client: ClientConfig{Timeout: 3 * time.Second}, MaxItems: 20} }
|
|
|
|
func (c Config) Validate() error {
|
|
if c.Client.Timeout <= 0 {
|
|
return config.Invalid("client.timeout", "must be positive")
|
|
}
|
|
if c.MaxItems < 0 {
|
|
return config.Invalid("maxItems", "must not be negative")
|
|
}
|
|
return nil
|
|
}
|
|
func newLoader() (*config.Loader, error) {
|
|
// Example of an instance-local extension. A TOML/etc. adapter can implement
|
|
// Decoder and return Document using that parser instead; no global registry.
|
|
return config.NewLoader(config.WithDecoder("custom", config.DecoderFunc(func(data []byte) (config.Document, error) {
|
|
return (config.JSONDecoder{}).Decode(data)
|
|
})))
|
|
}
|
|
func load(path string) (Config, error) {
|
|
loader, err := newLoader()
|
|
if err != nil {
|
|
return Config{}, err
|
|
}
|
|
return config.LoadProject(path, Default(), loader)
|
|
}
|
|
func run() error {
|
|
path := flag.String("config", "", "external configuration file")
|
|
format := flag.String("format", "yaml", "embedded example: json, yaml, xml")
|
|
flag.Parse()
|
|
if *path == "" {
|
|
data, err := examples.ReadFile("config." + *format)
|
|
if err != nil {
|
|
return fmt.Errorf("choose json, yaml or xml")
|
|
}
|
|
dir, err := os.MkdirTemp("", "goOmniConfiguration-")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer os.RemoveAll(dir)
|
|
*path = filepath.Join(dir, "config."+*format)
|
|
if err = os.WriteFile(*path, data, 0600); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
cfg, err := load(*path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// Print selected non-sensitive fields, never the whole configuration.
|
|
fmt.Printf("timeout=%s maxItems=%d allowed=%v\n", cfg.Client.Timeout, cfg.MaxItems, cfg.Allowed)
|
|
return nil
|
|
}
|
|
func main() {
|
|
if err := run(); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|