unistore: use the same connection string as grafana (#102387)

This commit is contained in:
Georges Chaudy
2025-03-19 13:56:54 +01:00
committed by GitHub
parent 3aba5cb2b7
commit 4927376f32
5 changed files with 97 additions and 53 deletions
@@ -11,6 +11,8 @@ import (
"xorm.io/xorm"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/storage/unified/sql/db"
)
@@ -18,6 +20,31 @@ import (
// driver.
const tlsConfigName = "db_engine_tls"
func getEngine(cfg *setting.Cfg) (*xorm.Engine, error) {
dbSection := cfg.SectionWithEnvOverrides("database")
dbType := dbSection.Key("type").String()
if dbType == "" {
return nil, fmt.Errorf("no database type specified")
}
switch dbType {
case dbTypeMySQL, dbTypePostgres, dbTypeSQLite:
config, err := sqlstore.NewDatabaseConfig(cfg, nil)
if err != nil {
return nil, nil
}
engine, err := xorm.NewEngine(dbType, config.ConnectionString)
if err != nil {
return nil, fmt.Errorf("open database: %w", err)
}
return engine, nil
default:
return nil, fmt.Errorf("unsupported database type: %s", dbType)
}
}
// Deprecated: use getEngine instead
func getEngineMySQL(getter confGetter) (*xorm.Engine, error) {
config := mysql.NewConfig()
config.User = getter.String("user")
@@ -108,6 +135,7 @@ func configureTLS(getter confGetter, config *mysql.Config) error {
return nil
}
// Deprecated: use getEngine instead
func getEnginePostgres(getter confGetter) (*xorm.Engine, error) {
dsnKV := map[string]string{
"user": getter.String("user"),
@@ -12,6 +12,7 @@ import (
"testing"
"time"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/require"
)
@@ -29,6 +30,64 @@ func newValidMySQLGetter(withKeyPrefix bool) confGetter {
}, prefix)
}
func TestGetEngine(t *testing.T) {
t.Parallel()
t.Run("MySQL engine", func(t *testing.T) {
t.Parallel()
cfg := setting.NewCfg()
dbSection := cfg.SectionWithEnvOverrides("database")
dbSection.Key("type").SetValue(dbTypeMySQL)
dbSection.Key("host").SetValue("/var/run/mysql.socket")
dbSection.Key("name").SetValue("grafana")
dbSection.Key("user").SetValue("user")
dbSection.Key("password").SetValue("password")
engine, err := getEngine(cfg)
require.NoError(t, err)
require.NotNil(t, engine)
})
t.Run("Postgres engine", func(t *testing.T) {
t.Parallel()
cfg := setting.NewCfg()
dbSection := cfg.SectionWithEnvOverrides("database")
dbSection.Key("type").SetValue(dbTypePostgres)
dbSection.Key("host").SetValue("localhost")
dbSection.Key("name").SetValue("grafana")
dbSection.Key("user").SetValue("user")
dbSection.Key("password").SetValue("password")
engine, err := getEngine(cfg)
require.NoError(t, err)
require.NotNil(t, engine)
})
t.Run("SQLite engine", func(t *testing.T) {
t.Parallel()
cfg := setting.NewCfg()
dbSection := cfg.SectionWithEnvOverrides("database")
dbSection.Key("type").SetValue(dbTypeSQLite)
dbSection.Key("path").SetValue(":memory:")
engine, err := getEngine(cfg)
require.NoError(t, err)
require.NotNil(t, engine)
})
t.Run("Unknown database type", func(t *testing.T) {
t.Parallel()
cfg := setting.NewCfg()
dbSection := cfg.SectionWithEnvOverrides("database")
dbSection.Key("type").SetValue("unknown")
engine, err := getEngine(cfg)
require.Error(t, err)
require.Nil(t, engine)
require.Contains(t, err.Error(), "unsupported database type")
})
}
func TestGetEngineMySQLFromConfig(t *testing.T) {
t.Parallel()
+7 -21
View File
@@ -23,6 +23,7 @@ import (
const (
dbTypeMySQL = "mysql"
dbTypePostgres = "postgres"
dbTypeSQLite = "sqlite3"
)
const grafanaDBInstrumentQueriesKey = "instrument_queries"
@@ -88,8 +89,7 @@ func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer trace.
dbType := getter.String("type")
grafanaDBType := fallbackGetter.String("type")
switch {
// First try with the config in the "resource_api" section, which is
// specific to Unified Storage
// Deprecated: First try with the config in the "resource_api" section, which is specific to Unified Storage
case dbType == dbTypePostgres:
p.registerMetrics = true
p.engine, err = getEnginePostgres(getter)
@@ -100,37 +100,23 @@ func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer trace.
p.engine, err = getEngineMySQL(getter)
return p, err
// TODO: add support for SQLite
case dbType != "":
return p, fmt.Errorf("invalid db type specified: %s", dbType)
// If we have an empty Resource API db config, try with the core Grafana
// database config
case grafanaDBType == dbTypePostgres:
// If we have an empty Resource API db config, try with the core Grafana database config
case grafanaDBType != "":
p.registerMetrics = true
p.engine, err = getEnginePostgres(fallbackGetter)
p.engine, err = getEngine(cfg)
return p, err
case grafanaDBType == dbTypeMySQL:
p.registerMetrics = true
p.engine, err = getEngineMySQL(fallbackGetter)
return p, err
// TODO: add support for SQLite
case grafanaDB != nil:
// try to use the grafana db connection
// try to use the grafana db connection (should only happen in tests)
if fallbackGetter.Bool(grafanaDBInstrumentQueriesKey) {
return nil, errGrafanaDBInstrumentedNotSupported
}
p.engine = grafanaDB.GetEngine()
return p, nil
default:
return p, fmt.Errorf("no db connection provided")
return p, fmt.Errorf("no database type specified")
}
}
@@ -6,6 +6,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util/testutil"
)
@@ -104,7 +105,8 @@ func TestReproIncident2144UsingGrafanaDB(t *testing.T) {
t.Run("Resource API provides a reasonable error for this case", func(t *testing.T) {
t.Parallel()
cfg := newCfgFromIniMap(t, cfgMap)
cfg := setting.NewCfg()
cfg.SectionWithEnvOverrides("database").Key(grafanaDBInstrumentQueriesKey).SetValue("true")
resourceDB, err := ProvideResourceDB(grafanaDB, cfg, nil)
require.Nil(t, resourceDB)
require.Error(t, err)