cvvvvv/internal/config/config.go

140 lines
3.4 KiB
Go

package config
import (
"log"
"os"
"path/filepath"
"time"
"github.com/kelseyhightower/envconfig"
"github.com/spf13/viper"
)
const (
defaultHTTPPort = "8000"
defaultHTTPRWTimeout = 10 * time.Second
defaultHTTPMaxHeaderMegabytes = 1
defaultAccessTokenTTL = 15 * time.Minute
defaultRefreshTokenTTL = 24 * time.Hour * 30
defaultLimiterRPS = 10
defaultLimiterBurst = 2
defaultLimiterTTL = 10 * time.Minute
defaultVerificationCodeLength = 8
EnvLocal = "local"
Prod = "prod"
)
type (
Config struct {
Environment string
HTTP HTTPConfig
Auth AuthConfig
Database string `mapstructure:"database"`
Limiter LimiterConfig
CacheTTL time.Duration `mapstructure:"ttl"`
}
AuthConfig struct {
ApiKeys map[string]string `mapstructure:"api_keys"`
}
HTTPConfig struct {
Host string `mapstructure:"host"`
Port string `mapstructure:"port"`
ReadTimeout time.Duration `mapstructure:"readTimeout"`
WriteTimeout time.Duration `mapstructure:"writeTimeout"`
MaxHeaderMegabytes int `mapstructure:"maxHeaderBytes"`
}
LimiterConfig struct {
RPS int
Burst int
TTL time.Duration
}
)
// Init populates Config struct with values from config file
// located at filepath and environment variables.
func Init(configsDir string) (*Config, error) {
populateDefaults()
if err := parseConfigFile(configsDir, os.Getenv("APP_ENV")); err != nil {
return nil, err
}
var cfg Config
if err := unmarshal(&cfg); err != nil {
return nil, err
}
//setFromEnv(&cfg)
return &cfg, nil
}
func unmarshal(cfg *Config) error {
if err := viper.UnmarshalKey("environment", &cfg.Environment); err != nil {
return err
}
if err := viper.UnmarshalKey("cache.ttl", &cfg.CacheTTL); err != nil {
return err
}
if err := viper.UnmarshalKey("http", &cfg.HTTP); err != nil {
return err
}
if err := viper.UnmarshalKey("auth", &cfg.Auth); err != nil {
return err
}
database := viper.GetString("database")
configDir := filepath.Dir(viper.ConfigFileUsed())
databaseAbsPath := filepath.Join(configDir, database)
viper.Set("database", databaseAbsPath)
if err := viper.UnmarshalKey("database", &cfg.Database); err != nil {
return err
}
return viper.UnmarshalKey("limiter", &cfg.Limiter)
}
func setFromEnv(cfg *Config) {
err := envconfig.Process("cvvvvv", &cfg)
if err != nil {
log.Fatal(err.Error())
}
}
func parseConfigFile(folder, env string) error {
viper.AddConfigPath(folder)
viper.SetConfigName("config")
if err := viper.ReadInConfig(); err != nil {
return err
}
if env == EnvLocal {
return nil
}
viper.SetConfigName(env)
return viper.MergeInConfig()
}
func populateDefaults() {
viper.SetDefault("http.port", defaultHTTPPort)
viper.SetDefault("http.max_header_megabytes", defaultHTTPMaxHeaderMegabytes)
viper.SetDefault("http.timeouts.read", defaultHTTPRWTimeout)
viper.SetDefault("http.timeouts.write", defaultHTTPRWTimeout)
viper.SetDefault("auth.accessTokenTTL", defaultAccessTokenTTL)
viper.SetDefault("auth.refreshTokenTTL", defaultRefreshTokenTTL)
viper.SetDefault("auth.verificationCodeLength", defaultVerificationCodeLength)
viper.SetDefault("limiter.rps", defaultLimiterRPS)
viper.SetDefault("limiter.burst", defaultLimiterBurst)
viper.SetDefault("limiter.ttl", defaultLimiterTTL)
}