100 lines
2.1 KiB
Go
100 lines
2.1 KiB
Go
package config
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type LoadOptions struct {
|
|
Path string
|
|
Units string
|
|
Timezone string
|
|
}
|
|
|
|
func Load(opts LoadOptions) (Config, error) {
|
|
cfg := Defaults()
|
|
|
|
path := opts.Path
|
|
if path == "" {
|
|
path = DefaultPath
|
|
}
|
|
|
|
if err := mergeFile(&cfg, path); err != nil {
|
|
if opts.Path != "" || !errors.Is(err, os.ErrNotExist) {
|
|
return Config{}, err
|
|
}
|
|
}
|
|
|
|
if opts.Units != "" {
|
|
cfg.WeatherAPI.Units = opts.Units
|
|
}
|
|
if opts.Timezone != "" {
|
|
cfg.WeatherAPI.Timezone = opts.Timezone
|
|
}
|
|
|
|
if err := normalizeReportModules(&cfg); err != nil {
|
|
return Config{}, err
|
|
}
|
|
|
|
secrets, err := loadSecrets(cfg.Secrets)
|
|
if err != nil {
|
|
return Config{}, err
|
|
}
|
|
|
|
if err := Validate(cfg); err != nil {
|
|
return Config{}, err
|
|
}
|
|
if err := applySecrets(secrets); err != nil {
|
|
return Config{}, err
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
func LoadFile(path string) (Config, error) {
|
|
return Load(LoadOptions{Path: path})
|
|
}
|
|
|
|
func mergeFile(cfg *Config, path string) error {
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return fmt.Errorf("read config %q: %w", path, err)
|
|
}
|
|
if err := rejectRetiredExecutionConfig(data); err != nil {
|
|
return fmt.Errorf("parse config %q: %w", path, err)
|
|
}
|
|
decoder := yaml.NewDecoder(bytes.NewReader(data))
|
|
decoder.KnownFields(true)
|
|
if err := decoder.Decode(cfg); err != nil {
|
|
return fmt.Errorf("parse config %q: %w", path, err)
|
|
}
|
|
if cfg.MissingSource.Sources == nil {
|
|
cfg.MissingSource.Sources = map[string]MissingSourcePolicy{}
|
|
}
|
|
if cfg.Reports == nil {
|
|
cfg.Reports = map[string]ReportConfig{}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func rejectRetiredExecutionConfig(data []byte) error {
|
|
var document yaml.Node
|
|
if err := yaml.Unmarshal(data, &document); err != nil {
|
|
return err
|
|
}
|
|
if len(document.Content) == 0 || document.Content[0].Kind != yaml.MappingNode {
|
|
return nil
|
|
}
|
|
root := document.Content[0]
|
|
for i := 0; i+1 < len(root.Content); i += 2 {
|
|
if root.Content[i].Value == "scriptorium" {
|
|
return fmt.Errorf("scriptorium configuration is no longer supported; migrate to promptkit configuration")
|
|
}
|
|
}
|
|
return nil
|
|
}
|