WASAPhoto/cmd/webapi/load-configuration.go

74 lines
2.4 KiB
Go

package main
import (
"errors"
"fmt"
"io"
"os"
"time"
"github.com/ardanlabs/conf"
"gopkg.in/yaml.v2"
)
// WebAPIConfiguration describes the web API configuration. This structure is automatically parsed by
// loadConfiguration and values from flags, environment variable or configuration file will be loaded.
type WebAPIConfiguration struct {
Config struct {
Path string `conf:"default:/conf/config.yml"`
}
Web struct {
APIHost string `conf:"default:0.0.0.0:3000"`
DebugHost string `conf:"default:0.0.0.0:4000"`
ReadTimeout time.Duration `conf:"default:5s"`
WriteTimeout time.Duration `conf:"default:5s"`
ShutdownTimeout time.Duration `conf:"default:5s"`
}
Debug bool
DB struct {
Filename string `conf:"default:/tmp/wasaphoto_data/wasaphoto.db"`
}
Data struct {
Path string `conf:"default:/tmp/wasaphoto_data/data"`
}
}
// loadConfiguration creates a WebAPIConfiguration starting from flags, environment variables and configuration file.
// It works by loading environment variables first, then update the config using command line flags, finally loading the
// configuration file (specified in WebAPIConfiguration.Config.Path).
// So, CLI parameters will override the environment, and configuration file will override everything.
// Note that the configuration file can be specified only via CLI or environment variable.
func loadConfiguration() (WebAPIConfiguration, error) {
var cfg WebAPIConfiguration
// Try to load configuration from environment variables and command line switches
if err := conf.Parse(os.Args[1:], "CFG", &cfg); err != nil {
if errors.Is(err, conf.ErrHelpWanted) {
usage, err := conf.Usage("CFG", &cfg)
if err != nil {
return cfg, fmt.Errorf("generating config usage: %w", err)
}
fmt.Println(usage) //nolint:forbidigo
return cfg, conf.ErrHelpWanted
}
return cfg, fmt.Errorf("parsing config: %w", err)
}
// Override values from YAML if specified and if it exists (useful in k8s/compose)
fp, err := os.Open(cfg.Config.Path)
if err != nil && !os.IsNotExist(err) {
return cfg, fmt.Errorf("can't read the config file, while it exists: %w", err)
} else if err == nil {
yamlFile, err := io.ReadAll(fp)
if err != nil {
return cfg, fmt.Errorf("can't read config file: %w", err)
}
err = yaml.Unmarshal(yamlFile, &cfg)
if err != nil {
return cfg, fmt.Errorf("can't unmarshal config file: %w", err)
}
_ = fp.Close()
}
return cfg, nil
}