Files
diun/internal/config/config.go
CrazyMax 1115234010 Add CLI to interact with Diun through gRPC (#382)
Add simple CLI to interact with Diun through gRPC
Create image and notif proto services
Compile and validate protos through a dedicated Dockerfile and bake target
Implement proto definitions
Move server as `serve` command
New commands `image` and `notif`
Refactor command line usage doc
Better CLI error handling
Tools build constraint to manage tools deps through go modules
Add upgrade notes

Co-authored-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-05-26 18:18:10 +02:00

87 lines
2.5 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"`
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(),
}
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)
}