(Feat): Initial Commit
Some checks failed
Build & Test / build-test (push) Has been cancelled
Build & Test / swagger-codegen-cli (push) Has been cancelled
CodeQL / Analyze (go) (push) Has been cancelled

This commit is contained in:
2026-07-03 19:41:31 +05:30
commit 7e940c83a7
461 changed files with 45002 additions and 0 deletions

223
internal/util/env.go Normal file
View 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
}