204 lines
6.7 KiB
Go
204 lines
6.7 KiB
Go
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fileserver/internal/utils"
|
|
"fmt"
|
|
"github.com/minio/minio-go/v7"
|
|
"github.com/minio/minio-go/v7/pkg/credentials"
|
|
"gorm.io/driver/postgres"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
"os"
|
|
)
|
|
|
|
// Application represents the top-level structure of the application's configuration.
|
|
type Application struct {
|
|
Server *Server `json:"server"` // Server configuration
|
|
Database *Database `json:"database"` // Database configuration
|
|
Minio *Minio `json:"minio"` // MinIO configuration
|
|
}
|
|
|
|
// Server holds the configuration related to the web server (e.g., host, port).
|
|
type Server struct {
|
|
Host string `json:"host"` // Hostname or IP address for the server
|
|
Port int `json:"port"` // Port number on which the server will run
|
|
}
|
|
|
|
// Database holds the configuration for connecting to a database (e.g., Postgres or SQLite).
|
|
type Database struct {
|
|
Url string `json:"url"` // Database URL (used in case of SQLite)
|
|
Driver string `json:"driver"` // Database driver (e.g., "postgres" or "sqlite")
|
|
Host string `json:"host"` // Hostname of the database server (used in case of PostgreSQL)
|
|
Port int `json:"port"` // Port number for the database connection
|
|
Name string `json:"name"` // Database name
|
|
Username string `json:"username"` // Database username
|
|
Password string `json:"password"` // Database password
|
|
SSLMode bool `json:"ssl-mode"` // Whether SSL is enabled for the connection
|
|
Timezone string `json:"timezone"` // Timezone for the database connection
|
|
}
|
|
|
|
// Minio holds the configuration for connecting to a MinIO server.
|
|
type Minio struct {
|
|
Url string `json:"url"` // MinIO server URL
|
|
Username string `json:"username"` // MinIO username
|
|
Password string `json:"password"` // MinIO password
|
|
Token string `json:"token"` // Optional token for MinIO authentication
|
|
Secure bool `json:"secure"` // Whether the connection is secure (HTTPS)
|
|
Region string `json:"region"` // MinIO server region
|
|
BucketLookup int `json:"bucketLookup"` // Bucket lookup strategy
|
|
}
|
|
|
|
// Global variables for the application configuration and clients.
|
|
var (
|
|
App Application // Application-level configuration
|
|
DB *gorm.DB // Database client (GORM)
|
|
MinIO *minio.Client // MinIO client
|
|
)
|
|
|
|
const (
|
|
configDir = "config" // Directory where the configuration files are stored
|
|
)
|
|
|
|
// Initialize reads the configuration file based on the profile (dev, test, prod),
|
|
// and initializes the MinIO and database clients based on the configuration.
|
|
func Initialize(profile string) error {
|
|
// Get the file path based on the profile
|
|
filename, err := checkProfileAndGetFilePath(profile)
|
|
if err != nil {
|
|
return fmt.Errorf("error checking profile: %v", err)
|
|
}
|
|
|
|
// Read the configuration file
|
|
content, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
return fmt.Errorf("error reading file: %v", err)
|
|
}
|
|
|
|
// Unmarshal the JSON content into the Application structure
|
|
if err = json.Unmarshal(content, &App); err != nil {
|
|
return fmt.Errorf("error unmarshaling JSON: %v", err)
|
|
}
|
|
|
|
// Initialize MinIO if MinIO configuration is provided
|
|
if App.Minio != nil {
|
|
if err := initializeMinIO(App.Minio); err != nil {
|
|
return fmt.Errorf("error initializing MinIO: %v", err)
|
|
}
|
|
fmt.Println("MinIO initialized")
|
|
}
|
|
|
|
// Initialize database if database configuration is provided
|
|
if App.Database != nil {
|
|
if err := initializeDatabase(App.Database); err != nil {
|
|
return fmt.Errorf("error initializing database: %v", err)
|
|
}
|
|
fmt.Println("Database initialized")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// checkProfileAndGetFilePath returns the correct configuration file path based on the profile (dev, test, prod).
|
|
func checkProfileAndGetFilePath(profile string) (string, error) {
|
|
var filename string
|
|
// Match the profile to its respective configuration file
|
|
switch {
|
|
case profile == "dev":
|
|
filename = fmt.Sprintf("%s/application-dev.json", configDir)
|
|
case profile == "test":
|
|
filename = fmt.Sprintf("%s/application-test.json", configDir)
|
|
case profile == "prod":
|
|
filename = fmt.Sprintf("%s/application.json", configDir)
|
|
default:
|
|
return "", fmt.Errorf("profile %s is not valid", profile)
|
|
}
|
|
return filename, nil
|
|
}
|
|
|
|
// initializeMinIO initializes the MinIO client using the provided configuration.
|
|
func initializeMinIO(minioConfig *Minio) error {
|
|
// Create a MinIO client with the given credentials and options
|
|
client, err := minio.New(minioConfig.Url, &minio.Options{
|
|
Creds: credentials.NewStaticV4(minioConfig.Username, minioConfig.Password, minioConfig.Token),
|
|
Secure: minioConfig.Secure,
|
|
Region: minioConfig.Region,
|
|
BucketLookup: getBucketLookup(minioConfig.BucketLookup),
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("cannot connect to MinIO %s: %v", minioConfig.Url, err)
|
|
}
|
|
MinIO = client
|
|
return nil
|
|
}
|
|
|
|
// getBucketLookup maps the integer value to the appropriate MinIO bucket lookup type.
|
|
func getBucketLookup(value int) minio.BucketLookupType {
|
|
switch value {
|
|
case 0:
|
|
return minio.BucketLookupAuto
|
|
case 1:
|
|
return minio.BucketLookupDNS
|
|
case 2:
|
|
return minio.BucketLookupPath
|
|
default:
|
|
return minio.BucketLookupAuto
|
|
}
|
|
}
|
|
|
|
// initializeDatabase initializes the database client based on the provided configuration.
|
|
func initializeDatabase(dbConfig *Database) error {
|
|
// Generate the database connection string based on the driver
|
|
switch dbConfig.Driver {
|
|
case "postgres":
|
|
var url string
|
|
if dbConfig.Url != "" {
|
|
url = fmt.Sprintf(
|
|
"postgres://%s:%s@%s/%s?sslmode=%s&TimeZone=%s",
|
|
dbConfig.Username,
|
|
dbConfig.Password,
|
|
dbConfig.Url,
|
|
utils.DefaultValue(dbConfig.Name, "postgres"),
|
|
getSSLModeValue(dbConfig.SSLMode),
|
|
utils.DefaultValue(dbConfig.Timezone, "UTC"),
|
|
)
|
|
} else {
|
|
url = fmt.Sprintf(
|
|
"host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=%s",
|
|
dbConfig.Host,
|
|
dbConfig.Username,
|
|
dbConfig.Password,
|
|
utils.DefaultValue(dbConfig.Name, "postgres"),
|
|
dbConfig.Port,
|
|
getSSLModeValue(dbConfig.SSLMode),
|
|
utils.DefaultValue(dbConfig.Timezone, "UTC"),
|
|
)
|
|
}
|
|
|
|
// Open PostgreSQL connection with GORM
|
|
db, err := gorm.Open(postgres.Open(url), &gorm.Config{})
|
|
if err != nil {
|
|
return fmt.Errorf("cannot connect to database %s@%s:%d", dbConfig.Username, dbConfig.Host, dbConfig.Port)
|
|
}
|
|
DB = db
|
|
case "sqlite":
|
|
// Open SQLite connection with GORM
|
|
db, err := gorm.Open(sqlite.Open(dbConfig.Url), &gorm.Config{})
|
|
if err != nil {
|
|
return fmt.Errorf("cannot connect to database %s", dbConfig.Url)
|
|
}
|
|
DB = db
|
|
default:
|
|
return fmt.Errorf("database type is not supported")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// getSSLModeValue returns "enable" or "disable" based on the boolean value for SSL mode.
|
|
func getSSLModeValue(mode bool) string {
|
|
if !mode {
|
|
return "disable"
|
|
}
|
|
return "enable"
|
|
}
|