diff --git a/deploy/config/db.json b/deploy/config/db.json index 3e15d00d..15805843 100644 --- a/deploy/config/db.json +++ b/deploy/config/db.json @@ -1,5 +1,6 @@ { "db": { + "type": "postgres", "host": "_DB_HOST", "port": "_DB_PORT", "name": "_DB_NAME", diff --git a/go.mod b/go.mod index 327f686f..817b1d81 100644 --- a/go.mod +++ b/go.mod @@ -30,11 +30,17 @@ require ( golang.org/x/crypto v0.41.0 golang.org/x/term v0.34.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 + gorm.io/driver/mysql v1.6.0 gorm.io/driver/postgres v1.6.0 gorm.io/driver/sqlite v1.5.7 gorm.io/gorm v1.30.1 ) +require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect +) + require ( github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.2 // indirect diff --git a/go.sum b/go.sum index 389cd3c9..a4c15fb7 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ= @@ -75,6 +77,8 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -247,6 +251,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg= +gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo= gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4= gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo= gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I= diff --git a/pkg/backend/backend.go b/pkg/backend/backend.go index 644fd35b..012fd264 100644 --- a/pkg/backend/backend.go +++ b/pkg/backend/backend.go @@ -6,15 +6,23 @@ import ( "github.com/spf13/viper" + "gorm.io/driver/mysql" "gorm.io/driver/postgres" + "gorm.io/driver/sqlite" "gorm.io/gorm" ) const ( // DBString to format connection string to database for postgres - DBString = "host=%s port=%s dbname=%s user=%s password=%s sslmode=%s" + PostgresDBString = "host=%s port=%s dbname=%s user=%s password=%s sslmode=%s" + // MySQLDBString to format connection string for MySQL + MySQLDBString = "%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local" // DBKey to identify the configuration JSON key DBKey = "db" + // Database types + DBTypePostgres = "postgres" + DBTypeMySQL = "mysql" + DBTypeSQLite = "sqlite" ) // DBManager have access to backend @@ -26,6 +34,7 @@ type DBManager struct { // JSONConfigurationDB to hold all backend configuration values type JSONConfigurationDB struct { + Type string `json:"type"` // Database type: postgres, mysql, sqlite Host string `json:"host"` Port string `json:"port"` Name string `json:"name"` @@ -36,6 +45,7 @@ type JSONConfigurationDB struct { MaxOpenConns int `json:"maxOpenConns"` ConnMaxLifetime int `json:"connMaxLifetime"` ConnRetry int `json:"connRetry"` + FilePath string `json:"filePath"` // Used for SQLite } // LoadConfiguration to load the DB configuration file and assign to variables @@ -60,13 +70,39 @@ func LoadConfiguration(file, key string) (JSONConfigurationDB, error) { // PrepareDSN to generate DB connection string func PrepareDSN(config JSONConfigurationDB) string { - return fmt.Sprintf( - DBString, config.Host, config.Port, config.Name, config.Username, config.Password, config.SSLMode) + switch config.Type { + case DBTypePostgres: + return fmt.Sprintf( + PostgresDBString, config.Host, config.Port, config.Name, config.Username, config.Password, config.SSLMode) + case DBTypeMySQL: + return fmt.Sprintf( + MySQLDBString, config.Username, config.Password, config.Host, config.Port, config.Name) + case DBTypeSQLite: + return config.FilePath + default: + // Default to postgres if not specified + return fmt.Sprintf( + PostgresDBString, config.Host, config.Port, config.Name, config.Username, config.Password, config.SSLMode) + } } -// GetDB to get PostgreSQL DB using GORM +// GetDB to get DB using GORM based on the configured driver func (db *DBManager) GetDB() (*gorm.DB, error) { - dbConn, err := gorm.Open(postgres.Open(db.DSN), &gorm.Config{}) + var dbConn *gorm.DB + var err error + + // Select the appropriate driver based on database type + switch db.Config.Type { + case DBTypePostgres: + dbConn, err = gorm.Open(postgres.Open(db.DSN), &gorm.Config{}) + case DBTypeMySQL: + dbConn, err = gorm.Open(mysql.Open(db.DSN), &gorm.Config{}) + case DBTypeSQLite: + dbConn, err = gorm.Open(sqlite.Open(db.DSN), &gorm.Config{}) + default: + // Default to postgres if type not specified + dbConn, err = gorm.Open(postgres.Open(db.DSN), &gorm.Config{}) + } if err != nil { return nil, err } diff --git a/pkg/config/flags.go b/pkg/config/flags.go index 2809e808..e384dbdd 100644 --- a/pkg/config/flags.go +++ b/pkg/config/flags.go @@ -41,6 +41,8 @@ const ( defDBConfigurationFile string = "config/db.json" // Default redis configuration file defRedisConfigurationFile string = "config/redis.json" + // Default db filepath for sqlite + defSQLiteDBFile string = "./osctrl.db" ) // ServiceFlagParams stores flag values for the each service @@ -422,6 +424,13 @@ func initDBFlags(params *ServiceFlagParams) []cli.Flag { EnvVars: []string{"DB_CONFIG_FILE"}, Destination: ¶ms.DBConfigFile, }, + &cli.StringFlag{ + Name: "db-type", + Value: "postgres", + Usage: "Type of backend to be used", + EnvVars: []string{"DB_TYPE"}, + Destination: ¶ms.DBConfigValues.Type, + }, &cli.StringFlag{ Name: "db-host", Value: "127.0.0.1", @@ -492,6 +501,13 @@ func initDBFlags(params *ServiceFlagParams) []cli.Flag { EnvVars: []string{"DB_CONN_RETRY"}, Destination: ¶ms.DBConfigValues.ConnRetry, }, + &cli.StringFlag{ + Name: "db-filepath", + Value: defSQLiteDBFile, + Usage: "File path to the SQLite database, only used when type is sqlite", + EnvVars: []string{"DB_SQLITE_FILEPATH"}, + Destination: ¶ms.DBConfigValues.FilePath, + }, } }