(Feat): Initial Commit
This commit is contained in:
223
internal/util/env.go
Normal file
223
internal/util/env.go
Normal file
@@ -0,0 +1,223 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user