224 lines
5.2 KiB
Go
224 lines
5.2 KiB
Go
// nolint:revive
|
|
package util
|
|
|
|
import (
|
|
"net/url"
|
|
"os"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
"golang.org/x/text/language"
|
|
)
|
|
|
|
const (
|
|
mgmtSecretLen = 16
|
|
)
|
|
|
|
var (
|
|
mgmtSecret string
|
|
mgmtSecretOnce sync.Once
|
|
)
|
|
|
|
func GetEnv(key string, defaultVal string) string {
|
|
if val, ok := os.LookupEnv(key); ok {
|
|
return val
|
|
}
|
|
|
|
return defaultVal
|
|
}
|
|
|
|
func GetEnvEnum(key string, defaultVal string, allowedValues []string) string {
|
|
if !slices.Contains(allowedValues, defaultVal) {
|
|
log.Panic().Str("key", key).Str("value", defaultVal).Msg("Default value is not in the allowed values list.")
|
|
}
|
|
|
|
val, ok := os.LookupEnv(key)
|
|
if !ok {
|
|
return defaultVal
|
|
}
|
|
|
|
if !slices.Contains(allowedValues, val) {
|
|
log.Error().Str("key", key).Str("value", val).Msg("Value is not allowed. Fallback to default value.")
|
|
return defaultVal
|
|
}
|
|
|
|
return val
|
|
}
|
|
|
|
func GetEnvAsInt(key string, defaultVal int) int {
|
|
strVal := GetEnv(key, "")
|
|
|
|
if val, err := strconv.Atoi(strVal); err == nil {
|
|
return val
|
|
}
|
|
|
|
return defaultVal
|
|
}
|
|
|
|
func GetEnvAsUint32(key string, defaultVal uint32) uint32 {
|
|
strVal := GetEnv(key, "")
|
|
|
|
if val, err := strconv.ParseUint(strVal, 10, 32); err == nil {
|
|
return uint32(val)
|
|
}
|
|
|
|
return defaultVal
|
|
}
|
|
|
|
func GetEnvAsUint8(key string, defaultVal uint8) uint8 {
|
|
strVal := GetEnv(key, "")
|
|
|
|
if val, err := strconv.ParseUint(strVal, 10, 8); err == nil {
|
|
return uint8(val)
|
|
}
|
|
|
|
return defaultVal
|
|
}
|
|
|
|
func GetEnvAsBool(key string, defaultVal bool) bool {
|
|
strVal := GetEnv(key, "")
|
|
|
|
if val, err := strconv.ParseBool(strVal); err == nil {
|
|
return val
|
|
}
|
|
|
|
return defaultVal
|
|
}
|
|
|
|
// GetEnvAsStringArr reads ENV and returns the values split by separator.
|
|
func GetEnvAsStringArr(key string, defaultVal []string, separator ...string) []string {
|
|
strVal := GetEnv(key, "")
|
|
|
|
if len(strVal) == 0 {
|
|
return defaultVal
|
|
}
|
|
|
|
sep := ","
|
|
if len(separator) >= 1 {
|
|
sep = separator[0]
|
|
}
|
|
|
|
return strings.Split(strVal, sep)
|
|
}
|
|
|
|
// GetEnvAsStringArrTrimmed reads ENV and returns the whitespace trimmed values split by separator.
|
|
func GetEnvAsStringArrTrimmed(key string, defaultVal []string, separator ...string) []string {
|
|
slc := GetEnvAsStringArr(key, defaultVal, separator...)
|
|
|
|
for i := range slc {
|
|
slc[i] = strings.TrimSpace(slc[i])
|
|
}
|
|
|
|
return slc
|
|
}
|
|
|
|
func GetEnvAsURL(key string, defaultVal string) *url.URL {
|
|
strVal := GetEnv(key, "")
|
|
|
|
if len(strVal) == 0 {
|
|
u, err := url.Parse(defaultVal)
|
|
if err != nil {
|
|
log.Panic().Str("key", key).Str("defaultVal", defaultVal).Err(err).Msg("Failed to parse default value for env variable as URL")
|
|
}
|
|
|
|
return u
|
|
}
|
|
|
|
u, err := url.Parse(strVal)
|
|
if err != nil {
|
|
log.Panic().Str("key", key).Str("strVal", strVal).Err(err).Msg("Failed to parse env variable as URL")
|
|
}
|
|
|
|
return u
|
|
}
|
|
|
|
func GetEnvAsLanguageTag(key string, defaultVal language.Tag) language.Tag {
|
|
strVal := GetEnv(key, "")
|
|
|
|
if len(strVal) == 0 {
|
|
return defaultVal
|
|
}
|
|
|
|
tag, err := language.Parse(strVal)
|
|
if err != nil {
|
|
log.Panic().Str("key", key).Str("strVal", strVal).Err(err).Msg("Failed to parse env variable as language.Tag")
|
|
}
|
|
|
|
return tag
|
|
}
|
|
|
|
// GetEnvAsLanguageTagArr reads ENV and returns the parsed values as []language.Tag split by separator.
|
|
func GetEnvAsLanguageTagArr(key string, defaultVal []language.Tag, separator ...string) []language.Tag {
|
|
strVal := GetEnv(key, "")
|
|
|
|
if len(strVal) == 0 {
|
|
return defaultVal
|
|
}
|
|
|
|
sep := ","
|
|
if len(separator) >= 1 {
|
|
sep = separator[0]
|
|
}
|
|
|
|
splitString := strings.Split(strVal, sep)
|
|
res := []language.Tag{}
|
|
for _, s := range splitString {
|
|
tag, err := language.Parse(s)
|
|
if err != nil {
|
|
log.Panic().Str("key", key).Str("itemVal", s).Err(err).Msg("Failed to parse item value from env variable as language.Tag")
|
|
}
|
|
res = append(res, tag)
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
// GetMgmtSecret returns the management secret for the app server, mainly used by health check and readiness endpoints.
|
|
// It first attempts to retrieve a value from the given environment variable and generates a cryptographically secure random string
|
|
// should no env var have been set.
|
|
// Failure to generate a random string will cause a panic as secret security cannot be guaranteed otherwise.
|
|
// Subsequent calls to GetMgmtSecret during the server's runtime will always return the same randomly generated secret for consistency.
|
|
func GetMgmtSecret(envKey string) string {
|
|
val := GetEnv(envKey, "")
|
|
|
|
if len(val) > 0 {
|
|
return val
|
|
}
|
|
|
|
mgmtSecretOnce.Do(func() {
|
|
var err error
|
|
mgmtSecret, err = GenerateRandomHexString(mgmtSecretLen)
|
|
if err != nil {
|
|
log.Panic().Err(err).Msg("Failed to generate random management secret")
|
|
}
|
|
|
|
log.Warn().Str("envKey", envKey).Str("mgmtSecret", mgmtSecret).Msg("Could not retrieve management secret from env key, using randomly generated one")
|
|
})
|
|
|
|
return mgmtSecret
|
|
}
|
|
|
|
func GetEnvAsLocation(key string, defaultVal string) *time.Location {
|
|
strVal := GetEnv(key, "")
|
|
|
|
if len(strVal) == 0 {
|
|
l, err := time.LoadLocation(defaultVal)
|
|
if err != nil {
|
|
log.Panic().Str("key", key).Str("defaultVal", defaultVal).Err(err).Msg("Failed to parse default value for env variable as location")
|
|
}
|
|
|
|
return l
|
|
}
|
|
|
|
l, err := time.LoadLocation(strVal)
|
|
if err != nil {
|
|
log.Panic().Str("key", key).Str("strVal", strVal).Err(err).Msg("Failed to parse env variable as location")
|
|
}
|
|
|
|
return l
|
|
}
|