126 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package config
 | 
						|
 | 
						|
import (
 | 
						|
	"flag"
 | 
						|
	"log"
 | 
						|
	"os"
 | 
						|
	"reflect"
 | 
						|
	"strconv"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
// getEnvString returns string from environment variable
 | 
						|
func getEnvString(env, def string) (val string) { //nolint:deadcode
 | 
						|
	val = os.Getenv(env)
 | 
						|
 | 
						|
	if val == "" {
 | 
						|
		return def
 | 
						|
	}
 | 
						|
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// getEnvInt returns int from environment variable
 | 
						|
func getEnvInt(env string, def int) (ret int) {
 | 
						|
	val := os.Getenv(env)
 | 
						|
 | 
						|
	if val == "" {
 | 
						|
		return def
 | 
						|
	}
 | 
						|
 | 
						|
	ret, err := strconv.Atoi(val)
 | 
						|
	if err != nil {
 | 
						|
		log.Fatalf("[ERROR] Environment variable is not numeric: %v\n", env)
 | 
						|
	}
 | 
						|
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// getEnvBool returns boolean from environment variable
 | 
						|
func getEnvBool(env string, def bool) bool {
 | 
						|
	var (
 | 
						|
		err    error
 | 
						|
		retVal bool
 | 
						|
		val    = os.Getenv(env)
 | 
						|
	)
 | 
						|
 | 
						|
	if len(val) == 0 {
 | 
						|
		return def
 | 
						|
	} else {
 | 
						|
		retVal, err = strconv.ParseBool(val)
 | 
						|
		if err != nil {
 | 
						|
			log.Fatalf("[ERROR] Environment variable is not boolean: %v\n", env)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return retVal
 | 
						|
}
 | 
						|
 | 
						|
// Init initializes the application configuration by reading default values from the struct's tags
 | 
						|
// and environment variables. Tags processed by this process are as follows:
 | 
						|
// `ignored:"true" env:"ENVIRONMENT_VARIABLE" default:"default value"`
 | 
						|
func Init() *Config {
 | 
						|
	cfg := DefaultConfig()
 | 
						|
 | 
						|
	cfgInfo, err := getStructInfo(cfg)
 | 
						|
	if err != nil {
 | 
						|
		log.Fatalf("[FATAL] %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	for _, info := range cfgInfo {
 | 
						|
		switch info.Type.String() {
 | 
						|
		case "string":
 | 
						|
			var dv string
 | 
						|
 | 
						|
			if info.DefaultValue != nil {
 | 
						|
				dv = info.DefaultValue.(string)
 | 
						|
			}
 | 
						|
			p := reflect.ValueOf(cfg).Elem().FieldByName(info.Name).Addr().Interface().(*string)
 | 
						|
			flag.StringVar(p, info.Name, getEnvString(info.Name, dv), "("+info.Key+")")
 | 
						|
		case "bool":
 | 
						|
			var dv bool
 | 
						|
 | 
						|
			if info.DefaultValue != nil {
 | 
						|
				dv = info.DefaultValue.(bool)
 | 
						|
			}
 | 
						|
			p := reflect.ValueOf(cfg).Elem().FieldByName(info.Name).Addr().Interface().(*bool)
 | 
						|
			flag.BoolVar(p, info.Name, getEnvBool(info.Name, dv), "("+info.Key+")")
 | 
						|
		case "int":
 | 
						|
			var dv int
 | 
						|
 | 
						|
			if info.DefaultValue != nil {
 | 
						|
				dv = int(info.DefaultValue.(int64))
 | 
						|
			}
 | 
						|
			p := reflect.ValueOf(cfg).Elem().FieldByName(info.Name).Addr().Interface().(*int)
 | 
						|
			flag.IntVar(p, info.Name, getEnvInt(info.Name, dv), "("+info.Key+")")
 | 
						|
		}
 | 
						|
	}
 | 
						|
	flag.Parse()
 | 
						|
 | 
						|
	// set logging level
 | 
						|
	cfg.setLogLevel()
 | 
						|
 | 
						|
	// validate some required values are defined.
 | 
						|
	// need to break this out to a required:"true" struct tag
 | 
						|
	if err = cfg.validate(); err != nil {
 | 
						|
		log.Fatalf("[FATAL] %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	// timezone & format configuration
 | 
						|
	cfg.TZoneUTC, _ = time.LoadLocation("UTC")
 | 
						|
	if err != nil {
 | 
						|
		log.Fatalf("[ERROR] Unable to parse timezone string. Please use one of the timezone database values listed here: %s", "https://en.wikipedia.org/wiki/List_of_tz_database_time_zones")
 | 
						|
	}
 | 
						|
	cfg.TZoneLocal, err = time.LoadLocation(cfg.TimeZoneLocal)
 | 
						|
	if err != nil {
 | 
						|
		log.Fatalf("[ERROR] Unable to parse timezone string. Please use one of the timezone database values listed here: %s", "https://en.wikipedia.org/wiki/List_of_tz_database_time_zones")
 | 
						|
	}
 | 
						|
	time.Now().Format(cfg.TimeFormat)
 | 
						|
 | 
						|
	// print running config
 | 
						|
	cfg.printRunningConfig(cfgInfo)
 | 
						|
 | 
						|
	log.Println("[INFO] initialization complete")
 | 
						|
	return cfg
 | 
						|
}
 |