crazy-max_diun/internal/config/config.go

89 lines
2.6 KiB
Go

package config
import (
"encoding/json"
"os"
"path"
"github.com/crazy-max/diun/v4/internal/model"
"github.com/crazy-max/gonfig"
"github.com/go-playground/validator/v10"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)
// Config holds configuration details
type Config struct {
Db *model.Db `yaml:"db,omitempty" json:"db,omitempty"`
Watch *model.Watch `yaml:"watch,omitempty" json:"watch,omitempty"`
Defaults *model.Defaults `yaml:"defaults,omitempty" json:"defaults,omitempty"`
Notif *model.Notif `yaml:"notif,omitempty" json:"notif,omitempty"`
RegOpts model.RegOpts `yaml:"regopts,omitempty" json:"regopts,omitempty" validate:"unique=Name,dive"`
Providers *model.Providers `yaml:"providers,omitempty" json:"providers,omitempty"`
}
// Load returns Config struct
func Load(config string) (*Config, error) {
cfg := Config{
Db: (&model.Db{}).GetDefaults(),
Watch: (&model.Watch{}).GetDefaults(),
Defaults: (&model.Defaults{}).GetDefaults(),
}
fileLoader := gonfig.NewFileLoader(gonfig.FileLoaderConfig{
Filename: config,
Finder: gonfig.Finder{
BasePaths: []string{"/etc/diun/diun", "$XDG_CONFIG_HOME/diun", "$HOME/.config/diun", "./diun"},
Extensions: []string{"yaml", "yml"},
},
})
if found, err := fileLoader.Load(&cfg); err != nil {
return nil, errors.Wrap(err, "failed to decode configuration from file")
} else if !found {
log.Debug().Msg("No configuration file found")
} else {
log.Info().Msgf("Configuration loaded from file: %s", fileLoader.GetFilename())
}
envLoader := gonfig.NewEnvLoader(gonfig.EnvLoaderConfig{
Prefix: "DIUN_",
})
if found, err := envLoader.Load(&cfg); err != nil {
return nil, errors.Wrap(err, "failed to decode configuration from environment variables")
} else if !found {
log.Debug().Msg("No DIUN_* environment variables defined")
} else {
log.Info().Msgf("Configuration loaded from %d environment variable(s)", len(envLoader.GetVars()))
}
if err := cfg.validate(); err != nil {
return nil, err
}
return &cfg, nil
}
func (cfg *Config) validate() error {
if len(cfg.Db.Path) > 0 {
if err := os.MkdirAll(path.Dir(cfg.Db.Path), os.ModePerm); err != nil {
return errors.Wrap(err, "cannot create database destination folder")
}
}
if cfg.Watch.Healthchecks != nil && len(cfg.Watch.Healthchecks.UUID) == 0 {
return errors.New("healthchecks UUID is required")
}
if cfg.Providers == nil {
return errors.New("at least one provider is required")
}
return validator.New().Struct(cfg)
}
// String returns the string representation of configuration
func (cfg *Config) String() string {
b, _ := json.MarshalIndent(cfg, "", " ")
return string(b)
}