Files
databasus/backend/internal/config/config.go
2025-12-25 21:26:53 +03:00

260 lines
7.5 KiB
Go

package config
import (
env_utils "databasus-backend/internal/util/env"
"databasus-backend/internal/util/logger"
"databasus-backend/internal/util/tools"
"os"
"path/filepath"
"strings"
"sync"
"github.com/ilyakaznacheev/cleanenv"
"github.com/joho/godotenv"
)
var log = logger.GetLogger()
const (
AppModeWeb = "web"
AppModeBackground = "background"
)
type EnvVariables struct {
IsTesting bool
DatabaseDsn string `env:"DATABASE_DSN" required:"true"`
EnvMode env_utils.EnvMode `env:"ENV_MODE" required:"true"`
PostgresesInstallDir string `env:"POSTGRES_INSTALL_DIR"`
MysqlInstallDir string `env:"MYSQL_INSTALL_DIR"`
MariadbInstallDir string `env:"MARIADB_INSTALL_DIR"`
MongodbInstallDir string `env:"MONGODB_INSTALL_DIR"`
DataFolder string
TempFolder string
SecretKeyPath string
TestGoogleDriveClientID string `env:"TEST_GOOGLE_DRIVE_CLIENT_ID"`
TestGoogleDriveClientSecret string `env:"TEST_GOOGLE_DRIVE_CLIENT_SECRET"`
TestGoogleDriveTokenJSON string `env:"TEST_GOOGLE_DRIVE_TOKEN_JSON"`
TestPostgres12Port string `env:"TEST_POSTGRES_12_PORT"`
TestPostgres13Port string `env:"TEST_POSTGRES_13_PORT"`
TestPostgres14Port string `env:"TEST_POSTGRES_14_PORT"`
TestPostgres15Port string `env:"TEST_POSTGRES_15_PORT"`
TestPostgres16Port string `env:"TEST_POSTGRES_16_PORT"`
TestPostgres17Port string `env:"TEST_POSTGRES_17_PORT"`
TestPostgres18Port string `env:"TEST_POSTGRES_18_PORT"`
TestMinioPort string `env:"TEST_MINIO_PORT"`
TestMinioConsolePort string `env:"TEST_MINIO_CONSOLE_PORT"`
TestAzuriteBlobPort string `env:"TEST_AZURITE_BLOB_PORT"`
TestNASPort string `env:"TEST_NAS_PORT"`
TestFTPPort string `env:"TEST_FTP_PORT"`
TestSFTPPort string `env:"TEST_SFTP_PORT"`
TestMysql57Port string `env:"TEST_MYSQL_57_PORT"`
TestMysql80Port string `env:"TEST_MYSQL_80_PORT"`
TestMysql84Port string `env:"TEST_MYSQL_84_PORT"`
TestMysql90Port string `env:"TEST_MYSQL_90_PORT"`
TestMariadb55Port string `env:"TEST_MARIADB_55_PORT"`
TestMariadb101Port string `env:"TEST_MARIADB_101_PORT"`
TestMariadb102Port string `env:"TEST_MARIADB_102_PORT"`
TestMariadb103Port string `env:"TEST_MARIADB_103_PORT"`
TestMariadb104Port string `env:"TEST_MARIADB_104_PORT"`
TestMariadb105Port string `env:"TEST_MARIADB_105_PORT"`
TestMariadb106Port string `env:"TEST_MARIADB_106_PORT"`
TestMariadb1011Port string `env:"TEST_MARIADB_1011_PORT"`
TestMariadb114Port string `env:"TEST_MARIADB_114_PORT"`
TestMariadb118Port string `env:"TEST_MARIADB_118_PORT"`
TestMariadb120Port string `env:"TEST_MARIADB_120_PORT"`
TestMongodb40Port string `env:"TEST_MONGODB_40_PORT"`
TestMongodb42Port string `env:"TEST_MONGODB_42_PORT"`
TestMongodb44Port string `env:"TEST_MONGODB_44_PORT"`
TestMongodb50Port string `env:"TEST_MONGODB_50_PORT"`
TestMongodb60Port string `env:"TEST_MONGODB_60_PORT"`
TestMongodb70Port string `env:"TEST_MONGODB_70_PORT"`
TestMongodb82Port string `env:"TEST_MONGODB_82_PORT"`
// oauth
GitHubClientID string `env:"GITHUB_CLIENT_ID"`
GitHubClientSecret string `env:"GITHUB_CLIENT_SECRET"`
GoogleClientID string `env:"GOOGLE_CLIENT_ID"`
GoogleClientSecret string `env:"GOOGLE_CLIENT_SECRET"`
// testing Telegram
TestTelegramBotToken string `env:"TEST_TELEGRAM_BOT_TOKEN"`
TestTelegramChatID string `env:"TEST_TELEGRAM_CHAT_ID"`
// testing Supabase
TestSupabaseHost string `env:"TEST_SUPABASE_HOST"`
TestSupabasePort string `env:"TEST_SUPABASE_PORT"`
TestSupabaseUsername string `env:"TEST_SUPABASE_USERNAME"`
TestSupabasePassword string `env:"TEST_SUPABASE_PASSWORD"`
TestSupabaseDatabase string `env:"TEST_SUPABASE_DATABASE"`
}
var (
env EnvVariables
once sync.Once
)
func GetEnv() EnvVariables {
once.Do(loadEnvVariables)
return env
}
func loadEnvVariables() {
// Get current working directory
cwd, err := os.Getwd()
if err != nil {
log.Warn("could not get current working directory", "error", err)
cwd = "."
}
backendRoot := cwd
for {
if _, err := os.Stat(filepath.Join(backendRoot, "go.mod")); err == nil {
break
}
parent := filepath.Dir(backendRoot)
if parent == backendRoot {
break
}
backendRoot = parent
}
envPaths := []string{
filepath.Join(cwd, ".env"),
filepath.Join(backendRoot, ".env"),
}
var loaded bool
for _, path := range envPaths {
log.Info("Trying to load .env", "path", path)
if err := godotenv.Load(path); err == nil {
log.Info("Successfully loaded .env", "path", path)
loaded = true
break
}
}
if !loaded {
log.Error("Error loading .env file: could not find .env in any location")
os.Exit(1)
}
err = cleanenv.ReadEnv(&env)
if err != nil {
log.Error("Configuration could not be loaded", "error", err)
os.Exit(1)
}
for _, arg := range os.Args {
if strings.Contains(arg, "test") {
env.IsTesting = true
break
}
}
if env.DatabaseDsn == "" {
log.Error("DATABASE_DSN is empty")
os.Exit(1)
}
if env.EnvMode == "" {
log.Error("ENV_MODE is empty")
os.Exit(1)
}
if env.EnvMode != "development" && env.EnvMode != "production" {
log.Error("ENV_MODE is invalid", "mode", env.EnvMode)
os.Exit(1)
}
log.Info("ENV_MODE loaded", "mode", env.EnvMode)
env.PostgresesInstallDir = filepath.Join(backendRoot, "tools", "postgresql")
tools.VerifyPostgresesInstallation(log, env.EnvMode, env.PostgresesInstallDir)
env.MysqlInstallDir = filepath.Join(backendRoot, "tools", "mysql")
tools.VerifyMysqlInstallation(log, env.EnvMode, env.MysqlInstallDir)
env.MariadbInstallDir = filepath.Join(backendRoot, "tools", "mariadb")
tools.VerifyMariadbInstallation(log, env.EnvMode, env.MariadbInstallDir)
env.MongodbInstallDir = filepath.Join(backendRoot, "tools", "mongodb")
tools.VerifyMongodbInstallation(log, env.EnvMode, env.MongodbInstallDir)
// Store the data and temp folders one level below the root
// (projectRoot/databasus-data -> /databasus-data)
env.DataFolder = filepath.Join(filepath.Dir(backendRoot), "databasus-data", "backups")
env.TempFolder = filepath.Join(filepath.Dir(backendRoot), "databasus-data", "temp")
env.SecretKeyPath = filepath.Join(filepath.Dir(backendRoot), "databasus-data", "secret.key")
if env.IsTesting {
if env.TestPostgres12Port == "" {
log.Error("TEST_POSTGRES_12_PORT is empty")
os.Exit(1)
}
if env.TestPostgres13Port == "" {
log.Error("TEST_POSTGRES_13_PORT is empty")
os.Exit(1)
}
if env.TestPostgres14Port == "" {
log.Error("TEST_POSTGRES_14_PORT is empty")
os.Exit(1)
}
if env.TestPostgres15Port == "" {
log.Error("TEST_POSTGRES_15_PORT is empty")
os.Exit(1)
}
if env.TestPostgres16Port == "" {
log.Error("TEST_POSTGRES_16_PORT is empty")
os.Exit(1)
}
if env.TestPostgres17Port == "" {
log.Error("TEST_POSTGRES_17_PORT is empty")
os.Exit(1)
}
if env.TestPostgres18Port == "" {
log.Error("TEST_POSTGRES_18_PORT is empty")
os.Exit(1)
}
if env.TestMinioPort == "" {
log.Error("TEST_MINIO_PORT is empty")
os.Exit(1)
}
if env.TestMinioConsolePort == "" {
log.Error("TEST_MINIO_CONSOLE_PORT is empty")
os.Exit(1)
}
if env.TestAzuriteBlobPort == "" {
log.Error("TEST_AZURITE_BLOB_PORT is empty")
os.Exit(1)
}
if env.TestNASPort == "" {
log.Error("TEST_NAS_PORT is empty")
os.Exit(1)
}
if env.TestTelegramBotToken == "" {
log.Error("TEST_TELEGRAM_BOT_TOKEN is empty")
os.Exit(1)
}
if env.TestTelegramChatID == "" {
log.Error("TEST_TELEGRAM_CHAT_ID is empty")
os.Exit(1)
}
}
log.Info("Environment variables loaded successfully!")
}