diff --git a/framework/configstore/config.go b/framework/configstore/config.go index 8875c7f99..e1c2b1f6c 100644 --- a/framework/configstore/config.go +++ b/framework/configstore/config.go @@ -12,6 +12,7 @@ type ConfigStoreType string const ( ConfigStoreTypeSQLite ConfigStoreType = "sqlite" ConfigStoreTypePostgres ConfigStoreType = "postgres" + ConfigStoreTypeMySQL ConfigStoreType = "mysql" ) // Config represents the configuration for the config store. @@ -58,6 +59,12 @@ func (c *Config) UnmarshalJSON(data []byte) error { return fmt.Errorf("failed to unmarshal postgres config: %w", err) } c.Config = &postgresConfig + case ConfigStoreTypeMySQL: + var mysqlConfig MySQLConfig + if err := json.Unmarshal(temp.Config, &mysqlConfig); err != nil { + return fmt.Errorf("failed to unmarshal mysql config: %w", err) + } + c.Config = &mysqlConfig default: return fmt.Errorf("unknown config store type: %s", temp.Type) } diff --git a/framework/configstore/mysql.go b/framework/configstore/mysql.go new file mode 100644 index 000000000..c0714c2b2 --- /dev/null +++ b/framework/configstore/mysql.go @@ -0,0 +1,34 @@ +package configstore + +import ( + "context" + "fmt" + + "github.com/maximhq/bifrost/core/schemas" + "gorm.io/driver/mysql" + "gorm.io/gorm" +) + +// MySQLConfig represents the configuration for a MySQL database. +type MySQLConfig struct { + User string `json:"user"` + Password string `json:"password"` + Host string `json:"host"` + Port int `json:"port"` + DBName string `json:"db_name"` + SSLMode string `json:"ssl_mode"` +} + +// newMySQLConfigStore creates a new MySQL config store. +func newMySQLConfigStore(ctx context.Context, config *MySQLConfig, logger schemas.Logger) (ConfigStore, error) { + db, err := gorm.Open(mysql.Open(fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&sslmode=%s", config.User, config.Password, config.Host, config.Port, config.DBName, config.SSLMode)), &gorm.Config{}) + if err != nil { + return nil, err + } + d := &RDBConfigStore{db: db, logger: logger} + // Run migrations + if err := triggerMigrations(ctx, db); err != nil { + return nil, err + } + return d, nil +} diff --git a/framework/configstore/store.go b/framework/configstore/store.go index 17f737aee..62c6a3c5f 100644 --- a/framework/configstore/store.go +++ b/framework/configstore/store.go @@ -130,6 +130,11 @@ func NewConfigStore(ctx context.Context, config *Config, logger schemas.Logger) return newPostgresConfigStore(ctx, postgresConfig, logger) } return nil, fmt.Errorf("invalid postgres config: %T", config.Config) + case ConfigStoreTypeMySQL: + if mysqlConfig, ok := config.Config.(*MySQLConfig); ok { + return newMySQLConfigStore(ctx, mysqlConfig, logger) + } + return nil, fmt.Errorf("invalid mysql config: %T", config.Config) } return nil, fmt.Errorf("unsupported config store type: %s", config.Type) } diff --git a/framework/go.mod b/framework/go.mod index 8217f579b..b43954702 100644 --- a/framework/go.mod +++ b/framework/go.mod @@ -16,6 +16,8 @@ require ( ) require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgx/v5 v5.6.0 // indirect @@ -93,5 +95,6 @@ require ( google.golang.org/protobuf v1.36.8 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + gorm.io/driver/mysql v1.6.0 gorm.io/driver/postgres v1.6.0 ) diff --git a/framework/go.sum b/framework/go.sum index 1ad8e9674..405501825 100644 --- a/framework/go.sum +++ b/framework/go.sum @@ -1,5 +1,7 @@ cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA= cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= @@ -102,6 +104,8 @@ github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ github.com/go-openapi/validate v0.21.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= +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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= @@ -360,6 +364,8 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ= diff --git a/transports/config.schema.json b/transports/config.schema.json index 063b8db46..221a05155 100644 --- a/transports/config.schema.json +++ b/transports/config.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://www.getbifrost.ai/schema", + "$id": "https://www.getbifrost.ai/schema", "title": "Bifrost Configuration Schema", "description": "Schema for Bifrost HTTP transport configuration", "type": "object", @@ -175,7 +175,8 @@ "type": "string", "enum": [ "sqlite", - "postgres" + "postgres", + "mysql" ], "description": "Configuration store type" }, @@ -249,6 +250,53 @@ ], "additionalProperties": false } + }, + { + "if": { + "properties": { + "type": { + "const": "mysql" + } + } + }, + "then": { + "type": "object", + "properties": { + "host": { + "type": "string", + "description": "Database host" + }, + "port": { + "type": "string", + "description": "Database port" + }, + "user": { + "type": "string", + "description": "Database user" + }, + "password": { + "type": "string", + "description": "Database password. Leave empty if you want to use IAM role authentication." + }, + "db_name": { + "type": "string", + "description": "Database name" + }, + "ssl_mode": { + "type": "string", + "description": "Database SSL mode" + } + }, + "required": [ + "host", + "port", + "user", + "password", + "db_name", + "ssl_mode" + ], + "additionalProperties": false + } } ] } @@ -267,7 +315,8 @@ "type": "string", "enum": [ "sqlite", - "postgres" + "postgres", + "mysql" ], "description": "Logs store type" }, @@ -340,6 +389,52 @@ ], "additionalProperties": false } + }, + { + "if": { + "properties": { + "../type": { + "const": "mysql" + } + } + }, + "then": { + "properties": { + "host": { + "type": "string", + "description": "Database host" + }, + "port": { + "type": "integer", + "description": "Database port" + }, + "user": { + "type": "string", + "description": "Database user" + }, + "password": { + "type": "string", + "description": "Database password. Leave empty if you want to use IAM role authentication." + }, + "db_name": { + "type": "string", + "description": "Database name" + }, + "ssl_mode": { + "type": "string", + "description": "Database SSL mode" + } + }, + "required": [ + "host", + "port", + "user", + "password", + "db_name", + "ssl_mode" + ], + "additionalProperties": false + } } ] }