From a21a232a8e57eb1cd1f664806e60be4f38ddbca8 Mon Sep 17 00:00:00 2001 From: Jeff Levin Date: Wed, 25 Sep 2024 15:21:39 -0800 Subject: [PATCH] Revert read replica POC (#93551) * Revert "chore: add replDB to team service (#91799)" This reverts commit c6ae2d7999aa6fc797db39e9d66c6fea70278f83. * Revert "experiment: use read replica for Get and Find Dashboards (#91706)" This reverts commit 54177ca619dbb5ded2dcb158405802d8dbdbc982. * Revert "QuotaService: refactor to use ReplDB for Get queries (#91333)" This reverts commit 299c142f6a6e8c5673cfdea9f87b56ac304f9834. * Revert "refactor replCfg to look more like plugins/plugin config (#91142)" This reverts commit ac0b4bb34d495914cbe8daad85b7c75c31e8070d. * Revert "chore (replstore): fix registration with multiple sql drivers, again (#90990)" This reverts commit daedb358dded00d349d9fac6106aaaa6bf18322e. * Revert "Chore (sqlstore): add validation and testing for repl config (#90683)" This reverts commit af19f039b62d9945377292a8e679ee258fd56b3d. * Revert "ReplStore: Add support for round robin load balancing between multiple read replicas (#90530)" This reverts commit 27b52b1507f5218a7b38046b4d96bc004d949d46. * Revert "DashboardStore: Use ReplDB and get dashboard quotas from the ReadReplica (#90235)" This reverts commit 8a6107cd35f6444c0674ee4230d3d6bcfbbd4a58. * Revert "accesscontrol service read replica (#89963)" This reverts commit 77a4869fcadf13827d76d5767d4de74812d6dd6d. * Revert "Fix: add mapping for the new mysqlRepl driver (#89551)" This reverts commit ab5a079bcc5b0f0a6929f0a3742eb2859d4a3498. * Revert "fix: sql instrumentation dual registration error (#89508)" This reverts commit d988f5c3b064fade6e96511e0024190c22d48e50. * Revert "Experimental Feature Toggle: databaseReadReplica (#89232)" This reverts commit 50244ed4a1435cbf3e3c87d4af34fd7937f7c259. --- .golangci.toml | 1 + .../feature-toggles/index.md | 1 - .../src/types/featureToggles.gen.ts | 1 - pkg/api/dashboard_test.go | 2 +- pkg/api/folder_bench_test.go | 20 +- pkg/api/org_users_test.go | 2 +- .../commands/conflict_user_command.go | 16 +- .../commands/conflict_user_command_test.go | 6 +- pkg/infra/db/db.go | 9 - pkg/infra/db/dbrepl.go | 19 -- .../statscollector/concurrent_users_test.go | 4 +- pkg/server/test_env.go | 3 - pkg/server/wire.go | 8 +- pkg/services/accesscontrol/acimpl/service.go | 4 +- .../acimpl/service_bench_test.go | 2 +- .../accesscontrol/acimpl/service_test.go | 4 +- .../accesscontrol/database/database.go | 20 +- .../accesscontrol/database/database_test.go | 4 +- .../database/externalservices.go | 4 +- .../database/externalservices_test.go | 17 +- .../accesscontrol/migrator/migrator.go | 6 +- .../migrator/migrator_bench_test.go | 2 +- .../accesscontrol/migrator/migrator_test.go | 2 +- .../resourcepermissions/service_test.go | 2 +- .../resourcepermissions/store_bench_test.go | 2 +- .../accesscontrol/accesscontrol_test.go | 2 +- .../annotationsimpl/annotations_test.go | 7 +- .../loki/historian_store_test.go | 8 +- .../annotationsimpl/xorm_store_test.go | 2 +- pkg/services/annotations/testutil/testutil.go | 7 +- pkg/services/dashboards/database/database.go | 79 +++-- .../database/database_folder_test.go | 42 +-- .../database/database_provisioning_test.go | 2 +- .../dashboards/database/database_test.go | 28 +- .../dashboards/service/dashboard_service.go | 1 + .../dashboard_service_integration_test.go | 30 +- .../service/service_test.go | 2 +- pkg/services/featuremgmt/registry.go | 7 - pkg/services/featuremgmt/toggles_gen.csv | 1 - pkg/services/featuremgmt/toggles_gen.go | 4 - pkg/services/featuremgmt/toggles_gen.json | 1 + .../folderimpl/dashboard_folder_store_test.go | 6 +- pkg/services/folder/folderimpl/folder_test.go | 12 +- .../libraryelements_delete_test.go | 5 +- .../libraryelements_get_test.go | 5 +- .../libraryelements/libraryelements_test.go | 26 +- .../librarypanels/librarypanels_test.go | 23 +- .../ngalert/api/api_provisioning_test.go | 5 +- .../ngalert/provisioning/alert_rules_test.go | 13 +- pkg/services/ngalert/store/alert_rule_test.go | 37 +-- pkg/services/ngalert/store/testing.go | 4 +- pkg/services/ngalert/tests/util.go | 5 +- pkg/services/ngalert/testutil/testutil.go | 4 +- pkg/services/org/orgimpl/store_test.go | 2 +- .../publicdashboards/api/query_test.go | 2 +- .../database/database_test.go | 80 +++-- .../publicdashboards/service/common_test.go | 4 +- .../publicdashboards/service/query_test.go | 15 +- .../publicdashboards/service/service_test.go | 20 +- pkg/services/quota/quotaimpl/quota.go | 2 +- pkg/services/quota/quotaimpl/quota_test.go | 7 +- pkg/services/quota/quotaimpl/store.go | 10 +- pkg/services/quota/quotaimpl/store_test.go | 2 +- pkg/services/searchV2/index_test.go | 5 +- pkg/services/serviceaccounts/tests/common.go | 10 +- pkg/services/sqlstore/database_config.go | 70 +---- pkg/services/sqlstore/database_config_test.go | 91 ------ pkg/services/sqlstore/database_wrapper.go | 21 -- pkg/services/sqlstore/migrator/dialect.go | 17 +- .../sqlstore/permissions/dashboard_test.go | 2 +- .../permissions/dashboards_bench_test.go | 2 +- pkg/services/sqlstore/replstore.go | 277 ------------------ pkg/services/sqlstore/replstore_test.go | 74 ----- pkg/services/stats/statsimpl/stats.go | 13 +- pkg/services/stats/statsimpl/stats_test.go | 12 +- pkg/services/team/teamimpl/store.go | 47 ++- pkg/services/team/teamimpl/store_test.go | 33 +-- pkg/services/team/teamimpl/team.go | 2 +- pkg/services/user/userimpl/store_test.go | 6 +- .../api/alerting/api_alertmanager_test.go | 8 +- pkg/tests/api/correlations/common_test.go | 5 +- .../api/dashboards/api_dashboards_test.go | 8 +- pkg/tests/api/folders/api_folder_test.go | 13 +- pkg/tests/api/plugins/api_plugins_test.go | 8 +- pkg/tests/api/stats/admin_test.go | 8 +- pkg/tests/apis/helper.go | 8 +- pkg/tests/testinfra/testinfra.go | 2 +- pkg/tests/utils.go | 11 +- 88 files changed, 416 insertions(+), 1010 deletions(-) delete mode 100644 pkg/infra/db/dbrepl.go delete mode 100644 pkg/services/sqlstore/replstore.go delete mode 100644 pkg/services/sqlstore/replstore_test.go diff --git a/.golangci.toml b/.golangci.toml index dc3ebd63afc..693ce6bc26e 100644 --- a/.golangci.toml +++ b/.golangci.toml @@ -1,6 +1,7 @@ [run] timeout = "20m" concurrency = 10 +allow-parallel-runners = true [linters-settings.exhaustive] default-signifies-exhaustive = true diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index 6edf736dadd..0ccd6b5c223 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -191,7 +191,6 @@ Experimental features might be changed or removed without prior notice. | `alertingCentralAlertHistory` | Enables the new central alert history. | | `pinNavItems` | Enables pinning of nav items | | `failWrongDSUID` | Throws an error if a datasource has an invalid UIDs | -| `databaseReadReplica` | Use a read replica for some database queries. | | `alertingApiServer` | Register Alerting APIs with the K8s API server | | `dashboardRestoreUI` | Enables the frontend to be able to restore a recently deleted dashboard | | `dataplaneAggregator` | Enable grafana dataplane aggregator | diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index 5b7e7fc1dcb..d4706619503 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -193,7 +193,6 @@ export interface FeatureToggles { openSearchBackendFlowEnabled?: boolean; ssoSettingsLDAP?: boolean; failWrongDSUID?: boolean; - databaseReadReplica?: boolean; zanzana?: boolean; passScopeToDashboardApi?: boolean; alertingApiServer?: boolean; diff --git a/pkg/api/dashboard_test.go b/pkg/api/dashboard_test.go index 617d836f22a..2ad87a053c6 100644 --- a/pkg/api/dashboard_test.go +++ b/pkg/api/dashboard_test.go @@ -820,7 +820,7 @@ func getDashboardShouldReturn200WithConfig(t *testing.T, sc *scenarioContext, pr features := featuremgmt.WithFeatures() var err error if dashboardStore == nil { - sql, cfg := db.InitTestReplDBWithCfg(t) + sql, cfg := db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) dashboardStore, err = database.ProvideDashboardStore(sql, cfg, features, tagimpl.ProvideService(sql), quotaService) require.NoError(t, err) diff --git a/pkg/api/folder_bench_test.go b/pkg/api/folder_bench_test.go index 059a0260287..58b4b7040d1 100644 --- a/pkg/api/folder_bench_test.go +++ b/pkg/api/folder_bench_test.go @@ -69,7 +69,7 @@ const ( ) type benchScenario struct { - db db.ReplDB + db db.DB // signedInUser is the user that is signed in to the server cfg *setting.Cfg signedInUser *user.SignedInUser @@ -202,7 +202,7 @@ func BenchmarkFolderListAndSearch(b *testing.B) { func setupDB(b testing.TB) benchScenario { b.Helper() - db, cfg := sqlstore.InitTestReplDB(b) + db, cfg := sqlstore.InitTestDB(b) IDs := map[int64]struct{}{} opts := sqlstore.NativeSettingsForDialect(db.GetDialect()) @@ -451,26 +451,26 @@ func setupServer(b testing.TB, sc benchScenario, features featuremgmt.FeatureTog quotaSrv := quotatest.New(false, nil) - dashStore, err := database.ProvideDashboardStore(sc.db, sc.cfg, features, tagimpl.ProvideService(sc.db.DB()), quotaSrv) + dashStore, err := database.ProvideDashboardStore(sc.db, sc.cfg, features, tagimpl.ProvideService(sc.db), quotaSrv) require.NoError(b, err) - folderStore := folderimpl.ProvideDashboardFolderStore(sc.db.DB()) + folderStore := folderimpl.ProvideDashboardFolderStore(sc.db) ac := acimpl.ProvideAccessControl(featuremgmt.WithFeatures(), zanzana.NewNoopClient()) - folderServiceWithFlagOn := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, folderStore, sc.db.DB(), features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + folderServiceWithFlagOn := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, folderStore, sc.db, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) cfg := setting.NewCfg() actionSets := resourcepermissions.NewActionSetService(features) acSvc := acimpl.ProvideOSSService( sc.cfg, acdb.ProvideService(sc.db), actionSets, localcache.ProvideService(), - features, tracing.InitializeTracerForTest(), zanzana.NewNoopClient(), sc.db.DB(), permreg.ProvidePermissionRegistry(), + features, tracing.InitializeTracerForTest(), zanzana.NewNoopClient(), sc.db, permreg.ProvidePermissionRegistry(), ) folderPermissions, err := ossaccesscontrol.ProvideFolderPermissions( - cfg, features, routing.NewRouteRegister(), sc.db.DB(), ac, license, &dashboards.FakeDashboardStore{}, folderServiceWithFlagOn, acSvc, sc.teamSvc, sc.userSvc, actionSets) + cfg, features, routing.NewRouteRegister(), sc.db, ac, license, &dashboards.FakeDashboardStore{}, folderServiceWithFlagOn, acSvc, sc.teamSvc, sc.userSvc, actionSets) require.NoError(b, err) dashboardPermissions, err := ossaccesscontrol.ProvideDashboardPermissions( - cfg, features, routing.NewRouteRegister(), sc.db.DB(), ac, license, &dashboards.FakeDashboardStore{}, folderServiceWithFlagOn, acSvc, sc.teamSvc, sc.userSvc, actionSets) + cfg, features, routing.NewRouteRegister(), sc.db, ac, license, &dashboards.FakeDashboardStore{}, folderServiceWithFlagOn, acSvc, sc.teamSvc, sc.userSvc, actionSets) require.NoError(b, err) dashboardSvc, err := dashboardservice.ProvideDashboardServiceImpl( @@ -486,10 +486,10 @@ func setupServer(b testing.TB, sc benchScenario, features featuremgmt.FeatureTog hs := &HTTPServer{ CacheService: localcache.New(5*time.Minute, 10*time.Minute), Cfg: sc.cfg, - SQLStore: sc.db.DB(), + SQLStore: sc.db, Features: features, QuotaService: quotaSrv, - SearchService: search.ProvideService(sc.cfg, sc.db.DB(), starSvc, dashboardSvc), + SearchService: search.ProvideService(sc.cfg, sc.db, starSvc, dashboardSvc), folderService: folderServiceWithFlagOn, DashboardService: dashboardSvc, } diff --git a/pkg/api/org_users_test.go b/pkg/api/org_users_test.go index 3c4caa64ecc..ea5f4930661 100644 --- a/pkg/api/org_users_test.go +++ b/pkg/api/org_users_test.go @@ -41,7 +41,7 @@ func setUpGetOrgUsersDB(t *testing.T, sqlStore db.DB, cfg *setting.Cfg) { cfg.AutoAssignOrg = true cfg.AutoAssignOrgId = int(testOrgID) - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(sqlStore), cfg) + quotaService := quotaimpl.ProvideService(sqlStore, cfg) orgService, err := orgimpl.ProvideService(sqlStore, cfg, quotaService) require.NoError(t, err) usrSvc, err := userimpl.ProvideService( diff --git a/pkg/cmd/grafana-cli/commands/conflict_user_command.go b/pkg/cmd/grafana-cli/commands/conflict_user_command.go index 01eb1336ec4..eb74c6f11f6 100644 --- a/pkg/cmd/grafana-cli/commands/conflict_user_command.go +++ b/pkg/cmd/grafana-cli/commands/conflict_user_command.go @@ -71,7 +71,7 @@ func initializeConflictResolver(cmd *utils.ContextCommandLine, f Formatter, ctx if err != nil { return nil, fmt.Errorf("%v: %w", "failed to load configuration", err) } - s, replstore, err := getSqlStore(cfg, tracer, features) + s, err := getSqlStore(cfg, tracer, features) if err != nil { return nil, fmt.Errorf("%v: %w", "failed to get to sql", err) } @@ -79,14 +79,14 @@ func initializeConflictResolver(cmd *utils.ContextCommandLine, f Formatter, ctx if err != nil { return nil, fmt.Errorf("%v: %w", "failed to get users with conflicting logins", err) } - quotaService := quotaimpl.ProvideService(replstore, cfg) + quotaService := quotaimpl.ProvideService(s, cfg) userService, err := userimpl.ProvideService(s, nil, cfg, nil, nil, tracer, quotaService, supportbundlestest.NewFakeBundleService()) if err != nil { return nil, fmt.Errorf("%v: %w", "failed to get user service", err) } routing := routing.ProvideRegister() - acService, err := acimpl.ProvideService(cfg, replstore, routing, nil, nil, nil, features, tracer, zanzana.NewNoopClient(), permreg.ProvidePermissionRegistry()) + acService, err := acimpl.ProvideService(cfg, s, routing, nil, nil, nil, features, tracer, zanzana.NewNoopClient(), permreg.ProvidePermissionRegistry()) if err != nil { return nil, fmt.Errorf("%v: %w", "failed to get access control", err) } @@ -95,15 +95,9 @@ func initializeConflictResolver(cmd *utils.ContextCommandLine, f Formatter, ctx return &resolver, nil } -func getSqlStore(cfg *setting.Cfg, tracer tracing.Tracer, features featuremgmt.FeatureToggles) (*sqlstore.SQLStore, *sqlstore.ReplStore, error) { +func getSqlStore(cfg *setting.Cfg, tracer tracing.Tracer, features featuremgmt.FeatureToggles) (*sqlstore.SQLStore, error) { bus := bus.ProvideBus(tracer) - ss, err := sqlstore.ProvideService(cfg, features, &migrations.OSSMigrations{}, bus, tracer) - if err != nil { - return nil, nil, err - } - - replStore, err := sqlstore.ProvideServiceWithReadReplica(ss, cfg, features, &migrations.OSSMigrations{}, bus, tracer) - return ss, replStore, err + return sqlstore.ProvideService(cfg, features, &migrations.OSSMigrations{}, bus, tracer) } func runListConflictUsers() func(context *cli.Context) error { diff --git a/pkg/cmd/grafana-cli/commands/conflict_user_command_test.go b/pkg/cmd/grafana-cli/commands/conflict_user_command_test.go index a43a07e1e53..c0aafacd3c0 100644 --- a/pkg/cmd/grafana-cli/commands/conflict_user_command_test.go +++ b/pkg/cmd/grafana-cli/commands/conflict_user_command_test.go @@ -636,7 +636,7 @@ func TestIntegrationMergeUser(t *testing.T) { } t.Run("should be able to merge user", func(t *testing.T) { // Restore after destructive operation - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) teamSvc, err := teamimpl.ProvideService(sqlStore, setting.NewCfg(), tracing.InitializeTracerForTest()) require.NoError(t, err) team1, err := teamSvc.CreateTeam(context.Background(), "team1 name", "", 1) @@ -714,10 +714,10 @@ func TestIntegrationMergeUser(t *testing.T) { } // get users - conflictUsers, err := GetUsersWithConflictingEmailsOrLogins(&cli.Context{Context: context.Background()}, sqlStore.SQLStore) + conflictUsers, err := GetUsersWithConflictingEmailsOrLogins(&cli.Context{Context: context.Background()}, sqlStore) require.NoError(t, err) r := ConflictResolver{ - Store: sqlStore.SQLStore, + Store: sqlStore, userService: usertest.NewUserServiceFake(), ac: actest.FakeService{}, } diff --git a/pkg/infra/db/db.go b/pkg/infra/db/db.go index c642a411840..5f61d5d3847 100644 --- a/pkg/infra/db/db.go +++ b/pkg/infra/db/db.go @@ -59,15 +59,6 @@ func InitTestDB(t sqlutil.ITestDB, opts ...InitTestDBOpt) *sqlstore.SQLStore { return db } -func InitTestReplDBWithCfg(t sqlutil.ITestDB, opts ...InitTestDBOpt) (*sqlstore.ReplStore, *setting.Cfg) { - return sqlstore.InitTestReplDB(t, opts...) -} - -func InitTestReplDB(t sqlutil.ITestDB, opts ...InitTestDBOpt) *sqlstore.ReplStore { - db, _ := InitTestReplDBWithCfg(t, opts...) - return db -} - func InitTestDBWithCfg(t sqlutil.ITestDB, opts ...InitTestDBOpt) (*sqlstore.SQLStore, *setting.Cfg) { return sqlstore.InitTestDB(t, opts...) } diff --git a/pkg/infra/db/dbrepl.go b/pkg/infra/db/dbrepl.go deleted file mode 100644 index 028989b44ec..00000000000 --- a/pkg/infra/db/dbrepl.go +++ /dev/null @@ -1,19 +0,0 @@ -package db - -import ( - "github.com/grafana/grafana/pkg/services/sqlstore" -) - -type ReplDB interface { - // DB is the primary database connection. - DB() *sqlstore.SQLStore - - // ReadReplica is the read-only database connection. If no read replica is configured, the implementation must return the primary DB. - ReadReplica() *sqlstore.SQLStore -} - -// FakeREplDBFromDBForTests returns a ReplDB that uses the given DB as the primary connection. It's a helper function for tests. -func FakeReplDBFromDB(primary DB) ReplDB { - ss := primary.(*sqlstore.SQLStore) - return sqlstore.FakeReplStoreFromStore(ss) -} diff --git a/pkg/infra/usagestats/statscollector/concurrent_users_test.go b/pkg/infra/usagestats/statscollector/concurrent_users_test.go index 919a74fa22e..decb1642657 100644 --- a/pkg/infra/usagestats/statscollector/concurrent_users_test.go +++ b/pkg/infra/usagestats/statscollector/concurrent_users_test.go @@ -24,7 +24,7 @@ func TestMain(m *testing.M) { } func TestConcurrentUsersMetrics(t *testing.T) { - sqlStore, cfg := db.InitTestReplDBWithCfg(t) + sqlStore, cfg := db.InitTestDBWithCfg(t) statsService := statsimpl.ProvideService(&setting.Cfg{}, sqlStore) s := createService(t, cfg, sqlStore, statsService) @@ -42,7 +42,7 @@ func TestConcurrentUsersMetrics(t *testing.T) { } func TestConcurrentUsersStats(t *testing.T) { - sqlStore, cfg := db.InitTestReplDBWithCfg(t) + sqlStore, cfg := db.InitTestDBWithCfg(t) statsService := statsimpl.ProvideService(&setting.Cfg{}, sqlStore) s := createService(t, cfg, sqlStore, statsService) diff --git a/pkg/server/test_env.go b/pkg/server/test_env.go index 104dc1242f6..51a54dde56c 100644 --- a/pkg/server/test_env.go +++ b/pkg/server/test_env.go @@ -16,7 +16,6 @@ import ( func ProvideTestEnv( server *Server, db db.DB, - repldb db.ReplDB, cfg *setting.Cfg, ns *notifications.NotificationServiceMock, grpcServer grpcserver.Provider, @@ -29,7 +28,6 @@ func ProvideTestEnv( return &TestEnv{ Server: server, SQLStore: db, - ReadReplStore: repldb, Cfg: cfg, NotificationService: ns, GRPCServer: grpcServer, @@ -44,7 +42,6 @@ func ProvideTestEnv( type TestEnv struct { Server *Server SQLStore db.DB - ReadReplStore db.ReplDB Cfg *setting.Cfg NotificationService *notifications.NotificationServiceMock GRPCServer grpcserver.Provider diff --git a/pkg/server/wire.go b/pkg/server/wire.go index 98edf7282b9..81574ec9677 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -391,13 +391,11 @@ var wireSet = wire.NewSet( wireBasicSet, metrics.WireSet, sqlstore.ProvideService, - sqlstore.ProvideServiceWithReadReplica, ngmetrics.ProvideService, wire.Bind(new(notifications.Service), new(*notifications.NotificationService)), wire.Bind(new(notifications.WebhookSender), new(*notifications.NotificationService)), wire.Bind(new(notifications.EmailSender), new(*notifications.NotificationService)), wire.Bind(new(db.DB), new(*sqlstore.SQLStore)), - wire.Bind(new(db.ReplDB), new(*sqlstore.ReplStore)), prefimpl.ProvideService, oauthtoken.ProvideService, wire.Bind(new(oauthtoken.OAuthTokenService), new(*oauthtoken.Service)), @@ -408,13 +406,11 @@ var wireCLISet = wire.NewSet( wireBasicSet, metrics.WireSet, sqlstore.ProvideService, - sqlstore.ProvideServiceWithReadReplica, ngmetrics.ProvideService, wire.Bind(new(notifications.Service), new(*notifications.NotificationService)), wire.Bind(new(notifications.WebhookSender), new(*notifications.NotificationService)), wire.Bind(new(notifications.EmailSender), new(*notifications.NotificationService)), wire.Bind(new(db.DB), new(*sqlstore.SQLStore)), - wire.Bind(new(db.ReplDB), new(*sqlstore.ReplStore)), prefimpl.ProvideService, oauthtoken.ProvideService, wire.Bind(new(oauthtoken.OAuthTokenService), new(*oauthtoken.Service)), @@ -425,14 +421,12 @@ var wireTestSet = wire.NewSet( ProvideTestEnv, metrics.WireSetForTest, sqlstore.ProvideServiceForTests, - sqlstore.ProvideServiceWithReadReplicaForTests, ngmetrics.ProvideServiceForTest, notifications.MockNotificationService, wire.Bind(new(notifications.Service), new(*notifications.NotificationServiceMock)), wire.Bind(new(notifications.WebhookSender), new(*notifications.NotificationServiceMock)), wire.Bind(new(notifications.EmailSender), new(*notifications.NotificationServiceMock)), wire.Bind(new(db.DB), new(*sqlstore.SQLStore)), - wire.Bind(new(db.ReplDB), new(*sqlstore.ReplStore)), prefimpl.ProvideService, oauthtoken.ProvideService, oauthtokentest.ProvideService, @@ -446,7 +440,7 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser func InitializeForTest(t sqlutil.ITestDB, cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*TestEnv, error) { wire.Build(wireExtsTestSet) - return &TestEnv{Server: &Server{}, SQLStore: &sqlstore.SQLStore{}, ReadReplStore: &sqlstore.ReplStore{}, Cfg: &setting.Cfg{}}, nil + return &TestEnv{Server: &Server{}, SQLStore: &sqlstore.SQLStore{}, Cfg: &setting.Cfg{}}, nil } func InitializeForCLI(cfg *setting.Cfg) (Runner, error) { diff --git a/pkg/services/accesscontrol/acimpl/service.go b/pkg/services/accesscontrol/acimpl/service.go index 3d5502afbf1..50616a33d3f 100644 --- a/pkg/services/accesscontrol/acimpl/service.go +++ b/pkg/services/accesscontrol/acimpl/service.go @@ -51,11 +51,11 @@ var SharedWithMeFolderPermission = accesscontrol.Permission{ var OSSRolesPrefixes = []string{accesscontrol.ManagedRolePrefix, accesscontrol.ExternalServiceRolePrefix} func ProvideService( - cfg *setting.Cfg, db db.ReplDB, routeRegister routing.RouteRegister, cache *localcache.CacheService, + cfg *setting.Cfg, db db.DB, routeRegister routing.RouteRegister, cache *localcache.CacheService, accessControl accesscontrol.AccessControl, actionResolver accesscontrol.ActionResolver, features featuremgmt.FeatureToggles, tracer tracing.Tracer, zclient zanzana.Client, permRegistry permreg.PermissionRegistry, ) (*Service, error) { - service := ProvideOSSService(cfg, database.ProvideService(db), actionResolver, cache, features, tracer, zclient, db.DB(), permRegistry) + service := ProvideOSSService(cfg, database.ProvideService(db), actionResolver, cache, features, tracer, zclient, db, permRegistry) api.NewAccessControlAPI(routeRegister, accessControl, service, features).RegisterAPIEndpoints() if err := accesscontrol.DeclareFixedRoles(service, cfg); err != nil { diff --git a/pkg/services/accesscontrol/acimpl/service_bench_test.go b/pkg/services/accesscontrol/acimpl/service_bench_test.go index 864676ae54b..19e13645263 100644 --- a/pkg/services/accesscontrol/acimpl/service_bench_test.go +++ b/pkg/services/accesscontrol/acimpl/service_bench_test.go @@ -27,7 +27,7 @@ import ( // - each managed role will have 3 permissions {"resources:action2", "resources:id:x"} where x belongs to [1, 3] func setupBenchEnv(b *testing.B, usersCount, resourceCount int) (accesscontrol.Service, *user.SignedInUser) { now := time.Now() - sqlStore := db.InitTestReplDB(b) + sqlStore := db.InitTestDB(b) store := database.ProvideService(sqlStore) acService := &Service{ cfg: setting.NewCfg(), diff --git a/pkg/services/accesscontrol/acimpl/service_test.go b/pkg/services/accesscontrol/acimpl/service_test.go index 6ac4e258c8f..7096b2fcac0 100644 --- a/pkg/services/accesscontrol/acimpl/service_test.go +++ b/pkg/services/accesscontrol/acimpl/service_test.go @@ -42,7 +42,7 @@ func setupTestEnv(t testing.TB) *Service { log: log.New("accesscontrol"), registrations: accesscontrol.RegistrationList{}, roles: accesscontrol.BuildBasicRoleDefinitions(), - store: database.ProvideService(db.InitTestReplDB(t)), + store: database.ProvideService(db.InitTestDB(t)), permRegistry: permreg.ProvidePermissionRegistry(), } require.NoError(t, ac.RegisterFixedRoles(context.Background())) @@ -66,7 +66,7 @@ func TestUsageMetrics(t *testing.T) { s := ProvideOSSService( cfg, - database.ProvideService(db.InitTestReplDB(t)), + database.ProvideService(db.InitTestDB(t)), &resourcepermissions.FakeActionSetSvc{}, localcache.ProvideService(), featuremgmt.WithFeatures(), diff --git a/pkg/services/accesscontrol/database/database.go b/pkg/services/accesscontrol/database/database.go index 8443af055f7..34ad42c332e 100644 --- a/pkg/services/accesscontrol/database/database.go +++ b/pkg/services/accesscontrol/database/database.go @@ -39,12 +39,12 @@ const ( WHERE br.role = ?` ) -func ProvideService(sql db.ReplDB) *AccessControlStore { +func ProvideService(sql db.DB) *AccessControlStore { return &AccessControlStore{sql} } type AccessControlStore struct { - sql db.ReplDB + sql db.DB } func (s *AccessControlStore) GetUserPermissions(ctx context.Context, query accesscontrol.GetUserPermissionsQuery) ([]accesscontrol.Permission, error) { @@ -52,7 +52,7 @@ func (s *AccessControlStore) GetUserPermissions(ctx context.Context, query acces defer span.End() result := make([]accesscontrol.Permission, 0) - err := s.sql.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { + err := s.sql.WithDbSession(ctx, func(sess *db.Session) error { if query.UserID == 0 && len(query.TeamIDs) == 0 && len(query.Roles) == 0 { // no permission to fetch return nil @@ -113,7 +113,7 @@ func (s *AccessControlStore) GetTeamsPermissions(ctx context.Context, query acce orgID := query.OrgID rolePrefixes := query.RolePrefixes result := make([]teamPermission, 0) - err := s.sql.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { + err := s.sql.WithDbSession(ctx, func(sess *db.Session) error { if len(teams) == 0 { // no permission to fetch return nil @@ -184,7 +184,7 @@ func (s *AccessControlStore) SearchUsersPermissions(ctx context.Context, orgID i } } - if err := s.sql.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { + if err := s.sql.WithDbSession(ctx, func(sess *db.Session) error { roleNameFilterJoin := "" if len(options.RolePrefixes) > 0 { roleNameFilterJoin = "INNER JOIN role AS r ON up.role_id = r.id" @@ -210,7 +210,7 @@ func (s *AccessControlStore) SearchUsersPermissions(ctx context.Context, orgID i params = append(params, userID) } - grafanaAdmin := fmt.Sprintf(grafanaAdminAssignsSQL, s.sql.ReadReplica().Quote("user")) + grafanaAdmin := fmt.Sprintf(grafanaAdminAssignsSQL, s.sql.Quote("user")) params = append(params, accesscontrol.RoleGrafanaAdmin) if userID >= 0 { grafanaAdmin += " AND sa.user_id = ?" @@ -299,11 +299,11 @@ func (s *AccessControlStore) GetUsersBasicRoles(ctx context.Context, userFilter IsAdmin bool `xorm:"is_admin"` } dbRoles := make([]UserOrgRole, 0) - if err := s.sql.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { + if err := s.sql.WithDbSession(ctx, func(sess *db.Session) error { // Find roles q := ` SELECT u.id, ou.role, u.is_admin - FROM ` + s.sql.ReadReplica().GetDialect().Quote("user") + ` AS u + FROM ` + s.sql.GetDialect().Quote("user") + ` AS u LEFT JOIN org_user AS ou ON u.id = ou.user_id WHERE (u.is_admin OR ou.org_id = ?) ` @@ -336,7 +336,7 @@ func (s *AccessControlStore) DeleteUserPermissions(ctx context.Context, orgID, u ctx, span := tracer.Start(ctx, "accesscontrol.database.DeleteUserPermissions") defer span.End() - err := s.sql.DB().WithDbSession(ctx, func(sess *db.Session) error { + err := s.sql.WithDbSession(ctx, func(sess *db.Session) error { roleDeleteQuery := "DELETE FROM user_role WHERE user_id = ?" roleDeleteParams := []any{roleDeleteQuery, userID} if orgID != accesscontrol.GlobalOrgID { @@ -404,7 +404,7 @@ func (s *AccessControlStore) DeleteTeamPermissions(ctx context.Context, orgID, t ctx, span := tracer.Start(ctx, "accesscontrol.database.DeleteTeamPermissions") defer span.End() - err := s.sql.DB().WithDbSession(ctx, func(sess *db.Session) error { + err := s.sql.WithDbSession(ctx, func(sess *db.Session) error { roleDeleteQuery := "DELETE FROM team_role WHERE team_id = ? AND org_id = ?" roleDeleteParams := []any{roleDeleteQuery, teamID, orgID} diff --git a/pkg/services/accesscontrol/database/database_test.go b/pkg/services/accesscontrol/database/database_test.go index e1d4f4c694b..7eaa72db708 100644 --- a/pkg/services/accesscontrol/database/database_test.go +++ b/pkg/services/accesscontrol/database/database_test.go @@ -470,8 +470,8 @@ func createUsersAndTeams(t *testing.T, store db.DB, svcs helperServices, orgID i return res } -func setupTestEnv(t testing.TB) (*database.AccessControlStore, rs.Store, user.Service, team.Service, org.Service, *sqlstore.ReplStore) { - sql, cfg := db.InitTestReplDBWithCfg(t) +func setupTestEnv(t testing.TB) (*database.AccessControlStore, rs.Store, user.Service, team.Service, org.Service, *sqlstore.SQLStore) { + sql, cfg := db.InitTestDBWithCfg(t) cfg.AutoAssignOrg = true cfg.AutoAssignOrgRole = "Viewer" cfg.AutoAssignOrgId = 1 diff --git a/pkg/services/accesscontrol/database/externalservices.go b/pkg/services/accesscontrol/database/externalservices.go index 3c658a85e8f..2ced82d908b 100644 --- a/pkg/services/accesscontrol/database/externalservices.go +++ b/pkg/services/accesscontrol/database/externalservices.go @@ -21,7 +21,7 @@ func (s *AccessControlStore) DeleteExternalServiceRole(ctx context.Context, exte defer span.End() uid := accesscontrol.PrefixedRoleUID(extServiceRoleName(externalServiceID)) - return s.sql.DB().WithDbSession(ctx, func(sess *db.Session) error { + return s.sql.WithDbSession(ctx, func(sess *db.Session) error { stored, errGet := getRoleByUID(ctx, sess, uid) if errGet != nil { // Role not found, nothing to do @@ -61,7 +61,7 @@ func (s *AccessControlStore) SaveExternalServiceRole(ctx context.Context, cmd ac role := genExternalServiceRole(cmd) assignment := genExternalServiceAssignment(cmd) - return s.sql.DB().WithDbSession(ctx, func(sess *db.Session) error { + return s.sql.WithDbSession(ctx, func(sess *db.Session) error { // Create or update the role existingRole, errSaveRole := s.saveRole(ctx, sess, &role) if errSaveRole != nil { diff --git a/pkg/services/accesscontrol/database/externalservices_test.go b/pkg/services/accesscontrol/database/externalservices_test.go index 7bde04735a5..e346f3be1d8 100644 --- a/pkg/services/accesscontrol/database/externalservices_test.go +++ b/pkg/services/accesscontrol/database/externalservices_test.go @@ -7,10 +7,9 @@ import ( "errors" "testing" - "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/services/accesscontrol" + "github.com/stretchr/testify/require" ) func TestAccessControlStore_SaveExternalServiceRole(t *testing.T) { @@ -115,7 +114,7 @@ func TestAccessControlStore_SaveExternalServiceRole(t *testing.T) { t.Run(tt.name, func(t *testing.T) { ctx := context.Background() s := &AccessControlStore{ - sql: db.InitTestReplDB(t), + sql: db.InitTestDB(t), } for i := range tt.runs { @@ -126,7 +125,7 @@ func TestAccessControlStore_SaveExternalServiceRole(t *testing.T) { } require.NoError(t, err) - errDBSession := s.sql.DB().WithDbSession(ctx, func(sess *db.Session) error { + errDBSession := s.sql.WithDbSession(ctx, func(sess *db.Session) error { storedRole, err := getRoleByUID(ctx, sess, accesscontrol.PrefixedRoleUID(extServiceRoleName(tt.runs[i].cmd.ExternalServiceID))) require.NoError(t, err) require.NotNil(t, storedRole) @@ -188,13 +187,13 @@ func TestAccessControlStore_DeleteExternalServiceRole(t *testing.T) { t.Run(tt.name, func(t *testing.T) { ctx := context.Background() s := &AccessControlStore{ - sql: db.InitTestReplDB(t), + sql: db.InitTestDB(t), } if tt.init != nil { tt.init(t, ctx, s) } roleID := int64(-1) - err := s.sql.DB().WithDbSession(ctx, func(sess *db.Session) error { + err := s.sql.WithDbSession(ctx, func(sess *db.Session) error { role, err := getRoleByUID(ctx, sess, accesscontrol.PrefixedRoleUID(extServiceRoleName(tt.id))) if err != nil && !errors.Is(err, accesscontrol.ErrRoleNotFound) { return err @@ -218,7 +217,7 @@ func TestAccessControlStore_DeleteExternalServiceRole(t *testing.T) { } // Assignments should be deleted - _ = s.sql.DB().WithDbSession(ctx, func(sess *db.Session) error { + _ = s.sql.WithDbSession(ctx, func(sess *db.Session) error { var assignment accesscontrol.UserRole count, err := sess.Where("role_id = ?", roleID).Count(&assignment) require.NoError(t, err) @@ -227,7 +226,7 @@ func TestAccessControlStore_DeleteExternalServiceRole(t *testing.T) { }) // Permissions should be deleted - _ = s.sql.DB().WithDbSession(ctx, func(sess *db.Session) error { + _ = s.sql.WithDbSession(ctx, func(sess *db.Session) error { var permission accesscontrol.Permission count, err := sess.Where("role_id = ?", roleID).Count(&permission) require.NoError(t, err) @@ -236,7 +235,7 @@ func TestAccessControlStore_DeleteExternalServiceRole(t *testing.T) { }) // Role should be deleted - _ = s.sql.DB().WithDbSession(ctx, func(sess *db.Session) error { + _ = s.sql.WithDbSession(ctx, func(sess *db.Session) error { storedRole, err := getRoleByUID(ctx, sess, accesscontrol.PrefixedRoleUID(extServiceRoleName(tt.id))) require.ErrorIs(t, err, accesscontrol.ErrRoleNotFound) require.Nil(t, storedRole) diff --git a/pkg/services/accesscontrol/migrator/migrator.go b/pkg/services/accesscontrol/migrator/migrator.go index 33317b4b5be..8ecc20ad553 100644 --- a/pkg/services/accesscontrol/migrator/migrator.go +++ b/pkg/services/accesscontrol/migrator/migrator.go @@ -19,14 +19,14 @@ const ( maxLen = 40 ) -func MigrateScopeSplit(db db.ReplDB, log log.Logger) error { +func MigrateScopeSplit(db db.DB, log log.Logger) error { t := time.Now() ctx := context.Background() cnt := 0 // Search for the permissions to update var permissions []ac.Permission - if errFind := db.DB().WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { + if errFind := db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { return sess.SQL("SELECT * FROM permission WHERE NOT scope = '' AND identifier = ''").Find(&permissions) }); errFind != nil { log.Error("Could not search for permissions to update", "migration", "scopeSplit", "error", errFind) @@ -76,7 +76,7 @@ func MigrateScopeSplit(db db.ReplDB, log log.Logger) error { delQuery = delQuery[:len(delQuery)-1] + ")" // Batch update the permissions - if errBatchUpdate := db.DB().GetSqlxSession().WithTransaction(ctx, func(tx *session.SessionTx) error { + if errBatchUpdate := db.GetSqlxSession().WithTransaction(ctx, func(tx *session.SessionTx) error { if _, errDel := tx.Exec(ctx, delQuery, delArgs...); errDel != nil { log.Error("Error deleting permissions", "migration", "scopeSplit", "error", errDel) return errDel diff --git a/pkg/services/accesscontrol/migrator/migrator_bench_test.go b/pkg/services/accesscontrol/migrator/migrator_bench_test.go index 7246b0812e3..5257a2fb2dd 100644 --- a/pkg/services/accesscontrol/migrator/migrator_bench_test.go +++ b/pkg/services/accesscontrol/migrator/migrator_bench_test.go @@ -10,7 +10,7 @@ import ( ) func benchScopeSplitConcurrent(b *testing.B, count int) { - store := db.InitTestReplDB(b) + store := db.InitTestDB(b) // Populate permissions require.NoError(b, batchInsertPermissions(count, store), "could not insert permissions") logger := log.New("migrator.test") diff --git a/pkg/services/accesscontrol/migrator/migrator_test.go b/pkg/services/accesscontrol/migrator/migrator_test.go index 0c98aa24a26..bfa35f17efc 100644 --- a/pkg/services/accesscontrol/migrator/migrator_test.go +++ b/pkg/services/accesscontrol/migrator/migrator_test.go @@ -46,7 +46,7 @@ func batchInsertPermissions(cnt int, sqlStore db.DB) error { // TestIntegrationMigrateScopeSplit tests the scope split migration // also tests the scope split truncation logic func TestIntegrationMigrateScopeSplitTruncation(t *testing.T) { - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) logger := log.New("accesscontrol.migrator.test") batchSize = 20 diff --git a/pkg/services/accesscontrol/resourcepermissions/service_test.go b/pkg/services/accesscontrol/resourcepermissions/service_test.go index c8c9dbb406c..94ead810dd7 100644 --- a/pkg/services/accesscontrol/resourcepermissions/service_test.go +++ b/pkg/services/accesscontrol/resourcepermissions/service_test.go @@ -493,7 +493,7 @@ func setupTestEnvironment(t *testing.T, ops Options) (*Service, user.Service, te cfg := setting.NewCfg() tracer := tracing.InitializeTracerForTest() - teamSvc, err := teamimpl.ProvideService(db.FakeReplDBFromDB(sql), cfg, tracer) + teamSvc, err := teamimpl.ProvideService(sql, cfg, tracer) require.NoError(t, err) orgSvc, err := orgimpl.ProvideService(sql, cfg, quotatest.New(false, nil)) diff --git a/pkg/services/accesscontrol/resourcepermissions/store_bench_test.go b/pkg/services/accesscontrol/resourcepermissions/store_bench_test.go index 60addeeee24..51a63a5deba 100644 --- a/pkg/services/accesscontrol/resourcepermissions/store_bench_test.go +++ b/pkg/services/accesscontrol/resourcepermissions/store_bench_test.go @@ -140,7 +140,7 @@ func GenerateDatasourcePermissions(b *testing.B, db db.DB, cfg *setting.Cfg, ac } func generateTeamsAndUsers(b *testing.B, store db.DB, cfg *setting.Cfg, users int) ([]int64, []int64) { - teamSvc, err := teamimpl.ProvideService(db.FakeReplDBFromDB(store), cfg, tracing.InitializeTracerForTest()) + teamSvc, err := teamimpl.ProvideService(store, cfg, tracing.InitializeTracerForTest()) require.NoError(b, err) numberOfTeams := int(math.Ceil(float64(users) / UsersPerTeam)) globalUserId := 0 diff --git a/pkg/services/annotations/accesscontrol/accesscontrol_test.go b/pkg/services/annotations/accesscontrol/accesscontrol_test.go index 00106f0f74b..42f767bec35 100644 --- a/pkg/services/annotations/accesscontrol/accesscontrol_test.go +++ b/pkg/services/annotations/accesscontrol/accesscontrol_test.go @@ -27,7 +27,7 @@ func TestIntegrationAuthorize(t *testing.T) { t.Skip("skipping integration test") } - sql, cfg := db.InitTestReplDBWithCfg(t) + sql, cfg := db.InitTestDBWithCfg(t) dash1 := testutil.CreateDashboard(t, sql, cfg, featuremgmt.WithFeatures(), dashboards.SaveDashboardCommand{ UserID: 1, diff --git a/pkg/services/annotations/annotationsimpl/annotations_test.go b/pkg/services/annotations/annotationsimpl/annotations_test.go index eb87f894916..7a1223bfb64 100644 --- a/pkg/services/annotations/annotationsimpl/annotations_test.go +++ b/pkg/services/annotations/annotationsimpl/annotations_test.go @@ -27,7 +27,6 @@ import ( "github.com/grafana/grafana/pkg/services/guardian" alertingStore "github.com/grafana/grafana/pkg/services/ngalert/store" "github.com/grafana/grafana/pkg/services/quota/quotatest" - "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest" "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" @@ -43,7 +42,7 @@ func TestIntegrationAnnotationListingWithRBAC(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - sql := db.InitTestReplDB(t) + sql := db.InitTestDB(t) cfg := setting.NewCfg() cfg.AnnotationMaximumTagsLength = 60 @@ -210,8 +209,8 @@ func TestIntegrationAnnotationListingWithInheritedRBAC(t *testing.T) { allDashboards := make([]dashInfo, 0, folder.MaxNestedFolderDepth+1) annotationsTexts := make([]string, 0, folder.MaxNestedFolderDepth+1) - setupFolderStructure := func() *sqlstore.ReplStore { - sql, cfg := db.InitTestReplDBWithCfg(t) + setupFolderStructure := func() db.DB { + sql, cfg := db.InitTestDBWithCfg(t) // enable nested folders so that the folder table is populated for all the tests features := featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders) diff --git a/pkg/services/annotations/annotationsimpl/loki/historian_store_test.go b/pkg/services/annotations/annotationsimpl/loki/historian_store_test.go index 6b378e7b8d6..bcd5e536ae0 100644 --- a/pkg/services/annotations/annotationsimpl/loki/historian_store_test.go +++ b/pkg/services/annotations/annotationsimpl/loki/historian_store_test.go @@ -44,7 +44,7 @@ func TestIntegrationAlertStateHistoryStore(t *testing.T) { t.Skip("skipping integration test") } - sql, cfg := db.InitTestReplDBWithCfg(t) + sql, cfg := db.InitTestDBWithCfg(t) dashboard1 := testutil.CreateDashboard(t, sql, cfg, featuremgmt.WithFeatures(), dashboards.SaveDashboardCommand{ UserID: 1, @@ -604,7 +604,7 @@ func TestBuildTransition(t *testing.T) { }) } -func createTestLokiStore(t *testing.T, sql *sqlstore.ReplStore, client lokiQueryClient) *LokiHistorianStore { +func createTestLokiStore(t *testing.T, sql *sqlstore.SQLStore, client lokiQueryClient) *LokiHistorianStore { t.Helper() ruleStore := store.SetupStoreForTesting(t, sql) @@ -618,7 +618,7 @@ func createTestLokiStore(t *testing.T, sql *sqlstore.ReplStore, client lokiQuery // createAlertRule creates an alert rule in the database and returns it. // If a generator is not specified, uniqueness of primary key is not guaranteed. -func createAlertRule(t *testing.T, sql *sqlstore.ReplStore, title string, generator *ngmodels.AlertRuleGenerator) *ngmodels.AlertRule { +func createAlertRule(t *testing.T, sql *sqlstore.SQLStore, title string, generator *ngmodels.AlertRuleGenerator) *ngmodels.AlertRule { t.Helper() if generator == nil { @@ -645,7 +645,7 @@ func createAlertRule(t *testing.T, sql *sqlstore.ReplStore, title string, genera // createAlertRuleFromDashboard creates an alert rule with a linked dashboard and panel in the database and returns it. // If a generator is not specified, uniqueness of primary key is not guaranteed. -func createAlertRuleFromDashboard(t *testing.T, sql *sqlstore.ReplStore, title string, dashboard dashboards.Dashboard, generator *ngmodels.AlertRuleGenerator) *ngmodels.AlertRule { +func createAlertRuleFromDashboard(t *testing.T, sql *sqlstore.SQLStore, title string, dashboard dashboards.Dashboard, generator *ngmodels.AlertRuleGenerator) *ngmodels.AlertRule { t.Helper() panelID := new(int64) diff --git a/pkg/services/annotations/annotationsimpl/xorm_store_test.go b/pkg/services/annotations/annotationsimpl/xorm_store_test.go index 6a5f11089e4..ae06428f835 100644 --- a/pkg/services/annotations/annotationsimpl/xorm_store_test.go +++ b/pkg/services/annotations/annotationsimpl/xorm_store_test.go @@ -29,7 +29,7 @@ func TestIntegrationAnnotations(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - sql := db.InitTestReplDB(t) + sql := db.InitTestDB(t) cfg := setting.NewCfg() cfg.AnnotationMaximumTagsLength = 60 diff --git a/pkg/services/annotations/testutil/testutil.go b/pkg/services/annotations/testutil/testutil.go index 6113e8f2367..3d71f85e40f 100644 --- a/pkg/services/annotations/testutil/testutil.go +++ b/pkg/services/annotations/testutil/testutil.go @@ -5,8 +5,6 @@ import ( "testing" "time" - "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/dashboards" @@ -17,6 +15,7 @@ import ( "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" + "github.com/stretchr/testify/require" ) func SetupRBACRole(t *testing.T, db db.DB, user *user.SignedInUser) *accesscontrol.Role { @@ -79,14 +78,14 @@ func SetupRBACPermission(t *testing.T, db db.DB, role *accesscontrol.Role, user require.NoError(t, err) } -func CreateDashboard(t *testing.T, db db.ReplDB, cfg *setting.Cfg, features featuremgmt.FeatureToggles, cmd dashboards.SaveDashboardCommand) *dashboards.Dashboard { +func CreateDashboard(t *testing.T, db db.DB, cfg *setting.Cfg, features featuremgmt.FeatureToggles, cmd dashboards.SaveDashboardCommand) *dashboards.Dashboard { t.Helper() dashboardStore, err := dashboardstore.ProvideDashboardStore( db, cfg, features, - tagimpl.ProvideService(db.DB()), + tagimpl.ProvideService(db), quotatest.New(false, nil), ) require.NoError(t, err) diff --git a/pkg/services/dashboards/database/database.go b/pkg/services/dashboards/database/database.go index b68ca7357fc..1eeb5fa5569 100644 --- a/pkg/services/dashboards/database/database.go +++ b/pkg/services/dashboards/database/database.go @@ -31,7 +31,7 @@ import ( var tracer = otel.Tracer("github.com/grafana/grafana/pkg/services/dashboard/database") type dashboardStore struct { - store db.ReplDB + store db.DB cfg *setting.Cfg log log.Logger features featuremgmt.FeatureToggles @@ -48,7 +48,7 @@ type dashboardTag struct { // DashboardStore implements the Store interface var _ dashboards.Store = (*dashboardStore)(nil) -func ProvideDashboardStore(sqlStore db.ReplDB, cfg *setting.Cfg, features featuremgmt.FeatureToggles, tagService tag.Service, quotaService quota.Service) (dashboards.Store, error) { +func ProvideDashboardStore(sqlStore db.DB, cfg *setting.Cfg, features featuremgmt.FeatureToggles, tagService tag.Service, quotaService quota.Service) (dashboards.Store, error) { s := &dashboardStore{store: sqlStore, cfg: cfg, log: log.New("dashboard-store"), features: features, tagService: tagService} defaultLimits, err := readQuotaConfig(cfg) @@ -76,7 +76,7 @@ func (d *dashboardStore) ValidateDashboardBeforeSave(ctx context.Context, dashbo defer span.End() isParentFolderChanged := false - err := d.store.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { + err := d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error { var err error isParentFolderChanged, err = getExistingDashboardByIDOrUIDForUpdate(sess, dashboard, overwrite) if err != nil { @@ -103,7 +103,7 @@ func (d *dashboardStore) GetProvisionedDataByDashboardID(ctx context.Context, da defer span.End() var data dashboards.DashboardProvisioning - err := d.store.DB().WithDbSession(ctx, func(sess *db.Session) error { + err := d.store.WithDbSession(ctx, func(sess *db.Session) error { _, err := sess.Where("dashboard_id = ?", dashboardID).Get(&data) return err }) @@ -119,7 +119,7 @@ func (d *dashboardStore) GetProvisionedDataByDashboardUID(ctx context.Context, o defer span.End() var provisionedDashboard dashboards.DashboardProvisioning - err := d.store.DB().WithDbSession(ctx, func(sess *db.Session) error { + err := d.store.WithDbSession(ctx, func(sess *db.Session) error { var dashboard dashboards.Dashboard exists, err := sess.Where("org_id = ? AND uid = ?", orgID, dashboardUID).Get(&dashboard) if err != nil { @@ -145,7 +145,7 @@ func (d *dashboardStore) GetProvisionedDashboardData(ctx context.Context, name s defer span.End() var result []*dashboards.DashboardProvisioning - err := d.store.DB().WithDbSession(ctx, func(sess *db.Session) error { + err := d.store.WithDbSession(ctx, func(sess *db.Session) error { return sess.Where("name = ?", name).Find(&result) }) return result, err @@ -157,7 +157,7 @@ func (d *dashboardStore) SaveProvisionedDashboard(ctx context.Context, cmd dashb var result *dashboards.Dashboard var err error - err = d.store.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { + err = d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error { result, err = saveDashboard(sess, &cmd, d.emitEntityEvent()) if err != nil { return err @@ -178,7 +178,7 @@ func (d *dashboardStore) SaveDashboard(ctx context.Context, cmd dashboards.SaveD var result *dashboards.Dashboard var err error - err = d.store.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { + err = d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error { result, err = saveDashboard(sess, &cmd, d.emitEntityEvent()) if err != nil { return err @@ -197,7 +197,7 @@ func (d *dashboardStore) UnprovisionDashboard(ctx context.Context, id int64) err ctx, span := tracer.Start(ctx, "dashboards.database.UnprovisionDashboard") defer span.End() - return d.store.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { + return d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error { _, err := sess.Where("dashboard_id = ?", id).Delete(&dashboards.DashboardProvisioning{}) return err }) @@ -207,7 +207,7 @@ func (d *dashboardStore) DeleteOrphanedProvisionedDashboards(ctx context.Context ctx, span := tracer.Start(ctx, "dashboards.database.DeleteOrphanedProvisionedDashboards") defer span.End() - return d.store.DB().WithDbSession(ctx, func(sess *db.Session) error { + return d.store.WithDbSession(ctx, func(sess *db.Session) error { var result []*dashboards.DashboardProvisioning convertedReaderNames := make([]any, len(cmd.ReaderNames)) @@ -241,8 +241,8 @@ func (d *dashboardStore) Count(ctx context.Context, scopeParams *quota.ScopePara } r := result{} - if err := d.store.ReadReplica().WithDbSession(ctx, func(sess *sqlstore.DBSession) error { - rawSQL := fmt.Sprintf("SELECT COUNT(*) AS count FROM dashboard WHERE is_folder=%s", d.store.ReadReplica().GetDialect().BooleanStr(false)) + if err := d.store.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { + rawSQL := fmt.Sprintf("SELECT COUNT(*) AS count FROM dashboard WHERE is_folder=%s", d.store.GetDialect().BooleanStr(false)) if _, err := sess.SQL(rawSQL).Get(&r); err != nil { return err } @@ -258,8 +258,8 @@ func (d *dashboardStore) Count(ctx context.Context, scopeParams *quota.ScopePara } if scopeParams != nil && scopeParams.OrgID != 0 { - if err := d.store.ReadReplica().WithDbSession(ctx, func(sess *sqlstore.DBSession) error { - rawSQL := fmt.Sprintf("SELECT COUNT(*) AS count FROM dashboard WHERE org_id=? AND is_folder=%s", d.store.ReadReplica().GetDialect().BooleanStr(false)) + if err := d.store.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { + rawSQL := fmt.Sprintf("SELECT COUNT(*) AS count FROM dashboard WHERE org_id=? AND is_folder=%s", d.store.GetDialect().BooleanStr(false)) if _, err := sess.SQL(rawSQL, scopeParams.OrgID).Get(&r); err != nil { return err } @@ -534,8 +534,8 @@ func (d *dashboardStore) GetDashboardsByPluginID(ctx context.Context, query *das defer span.End() var dashboards = make([]*dashboards.Dashboard, 0) - err := d.store.DB().WithDbSession(ctx, func(dbSession *db.Session) error { - whereExpr := "org_id=? AND plugin_id=? AND is_folder=" + d.store.DB().GetDialect().BooleanStr(false) + err := d.store.WithDbSession(ctx, func(dbSession *db.Session) error { + whereExpr := "org_id=? AND plugin_id=? AND is_folder=" + d.store.GetDialect().BooleanStr(false) err := dbSession.Where(whereExpr, query.OrgID, query.PluginID).Find(&dashboards) return err @@ -545,7 +545,6 @@ func (d *dashboardStore) GetDashboardsByPluginID(ctx context.Context, query *das } return dashboards, nil } - func (d *dashboardStore) GetSoftDeletedDashboard(ctx context.Context, orgID int64, uid string) (*dashboards.Dashboard, error) { ctx, span := tracer.Start(ctx, "dashboards.database.GetSoftDeletedDashboard") defer span.End() @@ -555,7 +554,7 @@ func (d *dashboardStore) GetSoftDeletedDashboard(ctx context.Context, orgID int6 } var queryResult *dashboards.Dashboard - err := d.store.DB().WithDbSession(ctx, func(sess *db.Session) error { + err := d.store.WithDbSession(ctx, func(sess *db.Session) error { dashboard := dashboards.Dashboard{OrgID: orgID, UID: uid} has, err := sess.Where("deleted IS NOT NULL").Get(&dashboard) @@ -576,7 +575,7 @@ func (d *dashboardStore) RestoreDashboard(ctx context.Context, orgID int64, dash ctx, span := tracer.Start(ctx, "dashboards.database.RestoreDashboard") defer span.End() - return d.store.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { + return d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error { if folder == nil || folder.UID == "" { _, err := sess.Exec("UPDATE dashboard SET deleted=NULL, folder_id=0, folder_uid=NULL WHERE org_id=? AND uid=?", orgID, dashboardUID) return err @@ -591,7 +590,7 @@ func (d *dashboardStore) SoftDeleteDashboard(ctx context.Context, orgID int64, d ctx, span := tracer.Start(ctx, "dashboards.database.SoftDeleteDashboard") defer span.End() - return d.store.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { + return d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error { _, err := sess.Exec("UPDATE dashboard SET deleted=? WHERE org_id=? AND uid=?", time.Now(), orgID, dashboardUID) return err }) @@ -605,7 +604,7 @@ func (d *dashboardStore) SoftDeleteDashboardsInFolders(ctx context.Context, orgI return nil } - return d.store.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { + return d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error { s := strings.Builder{} s.WriteString("UPDATE dashboard SET deleted=? WHERE ") s.WriteString(fmt.Sprintf("folder_uid IN (%s)", strings.Repeat("?,", len(folderUids)-1)+"?")) @@ -617,7 +616,7 @@ func (d *dashboardStore) SoftDeleteDashboardsInFolders(ctx context.Context, orgI for _, folderUID := range folderUids { args = append(args, folderUID) } - args = append(args, orgID, d.store.DB().GetDialect().BooleanStr(false)) + args = append(args, orgID, d.store.GetDialect().BooleanStr(false)) _, err := sess.Exec(args...) return err @@ -628,7 +627,7 @@ func (d *dashboardStore) DeleteDashboard(ctx context.Context, cmd *dashboards.De ctx, span := tracer.Start(ctx, "dashboards.database.DeleteDashboard") defer span.End() - return d.store.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { + return d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error { return d.deleteDashboard(cmd, sess, d.emitEntityEvent()) }) } @@ -664,14 +663,14 @@ func (d *dashboardStore) deleteDashboard(cmd *dashboards.DeleteDashboardCommand, if dashboard.IsFolder { if !d.features.IsEnabledGlobally(featuremgmt.FlagDashboardRestore) { - sqlStatements = append(sqlStatements, statement{SQL: "DELETE FROM dashboard WHERE org_id = ? AND folder_uid = ? AND is_folder = ? AND deleted IS NULL", args: []any{dashboard.OrgID, dashboard.UID, d.store.DB().GetDialect().BooleanStr(false)}}) + sqlStatements = append(sqlStatements, statement{SQL: "DELETE FROM dashboard WHERE org_id = ? AND folder_uid = ? AND is_folder = ? AND deleted IS NULL", args: []any{dashboard.OrgID, dashboard.UID, d.store.GetDialect().BooleanStr(false)}}) if err := d.deleteChildrenDashboardAssociations(sess, &dashboard); err != nil { return err } } else { // soft delete all dashboards in the folder - sqlStatements = append(sqlStatements, statement{SQL: "UPDATE dashboard SET deleted = ? WHERE org_id = ? AND folder_uid = ? AND is_folder = ? ", args: []any{time.Now(), dashboard.OrgID, dashboard.UID, d.store.DB().GetDialect().BooleanStr(false)}}) + sqlStatements = append(sqlStatements, statement{SQL: "UPDATE dashboard SET deleted = ? WHERE org_id = ? AND folder_uid = ? AND is_folder = ? ", args: []any{time.Now(), dashboard.OrgID, dashboard.UID, d.store.GetDialect().BooleanStr(false)}}) } // remove all access control permission with folder scope @@ -788,7 +787,7 @@ func (d *dashboardStore) GetDashboard(ctx context.Context, query *dashboards.Get defer span.End() var queryResult *dashboards.Dashboard - err := d.store.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { + err := d.store.WithDbSession(ctx, func(sess *db.Session) error { metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Dashboard).Inc() // nolint:staticcheck if query.ID == 0 && len(query.UID) == 0 && (query.Title == nil || (query.FolderID == nil && query.FolderUID == nil)) { @@ -833,7 +832,7 @@ func (d *dashboardStore) GetDashboardUIDByID(ctx context.Context, query *dashboa defer span.End() us := &dashboards.DashboardRef{} - err := d.store.DB().WithDbSession(ctx, func(sess *db.Session) error { + err := d.store.WithDbSession(ctx, func(sess *db.Session) error { var rawSQL = `SELECT uid, slug from dashboard WHERE Id=?` exists, err := sess.SQL(rawSQL, query.ID).Get(us) if err != nil { @@ -854,7 +853,7 @@ func (d *dashboardStore) GetDashboards(ctx context.Context, query *dashboards.Ge defer span.End() var dashboards = make([]*dashboards.Dashboard, 0) - err := d.store.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { + err := d.store.WithDbSession(ctx, func(sess *db.Session) error { if len(query.DashboardIDs) == 0 && len(query.DashboardUIDs) == 0 { return star.ErrCommandValidationFailed } @@ -884,7 +883,7 @@ func (d *dashboardStore) FindDashboards(ctx context.Context, query *dashboards.F ctx, span := tracer.Start(ctx, "dashboards.database.FindDashboards") defer span.End() - recursiveQueriesAreSupported, err := d.store.ReadReplica().RecursiveQueriesAreSupported() + recursiveQueriesAreSupported, err := d.store.RecursiveQueriesAreSupported() if err != nil { return nil, err } @@ -917,11 +916,11 @@ func (d *dashboardStore) FindDashboards(ctx context.Context, query *dashboards.F } if len(query.Title) > 0 { - filters = append(filters, searchstore.TitleFilter{Dialect: d.store.ReadReplica().GetDialect(), Title: query.Title}) + filters = append(filters, searchstore.TitleFilter{Dialect: d.store.GetDialect(), Title: query.Title}) } if len(query.Type) > 0 { - filters = append(filters, searchstore.TypeFilter{Dialect: d.store.ReadReplica().GetDialect(), Type: query.Type}) + filters = append(filters, searchstore.TypeFilter{Dialect: d.store.GetDialect(), Type: query.Type}) } metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Dashboard).Inc() // nolint:staticcheck @@ -931,7 +930,7 @@ func (d *dashboardStore) FindDashboards(ctx context.Context, query *dashboards.F if len(query.FolderUIDs) > 0 { filters = append(filters, searchstore.FolderUIDFilter{ - Dialect: d.store.ReadReplica().GetDialect(), + Dialect: d.store.GetDialect(), OrgID: orgID, UIDs: query.FolderUIDs, NestedFoldersEnabled: d.features.IsEnabled(ctx, featuremgmt.FlagNestedFolders), @@ -948,7 +947,7 @@ func (d *dashboardStore) FindDashboards(ctx context.Context, query *dashboards.F filters = append(filters, searchstore.DeletedFilter{Deleted: query.IsDeleted}) var res []dashboards.DashboardSearchProjection - sb := &searchstore.Builder{Dialect: d.store.ReadReplica().GetDialect(), Filters: filters, Features: d.features} + sb := &searchstore.Builder{Dialect: d.store.GetDialect(), Filters: filters, Features: d.features} limit := query.Limit if limit < 1 { @@ -962,7 +961,7 @@ func (d *dashboardStore) FindDashboards(ctx context.Context, query *dashboards.F sql, params := sb.ToSQL(limit, page) - err = d.store.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { + err = d.store.WithDbSession(ctx, func(sess *db.Session) error { return sess.SQL(sql, params...).Find(&res) }) @@ -978,7 +977,7 @@ func (d *dashboardStore) GetDashboardTags(ctx context.Context, query *dashboards defer span.End() queryResult := make([]*dashboards.DashboardTagCloudItem, 0) - err := d.store.DB().WithDbSession(ctx, func(dbSession *db.Session) error { + err := d.store.WithDbSession(ctx, func(dbSession *db.Session) error { sql := `SELECT COUNT(*) as count, term @@ -1009,7 +1008,7 @@ func (d *dashboardStore) CountDashboardsInFolders( return 0, nil } var count int64 - err := d.store.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { + err := d.store.WithDbSession(ctx, func(sess *db.Session) error { metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Dashboard).Inc() s := strings.Builder{} args := make([]any, 0, 3) @@ -1023,7 +1022,7 @@ func (d *dashboardStore) CountDashboardsInFolders( } } s.WriteString(" AND org_id = ? AND is_folder = ? AND deleted IS NULL") - args = append(args, req.OrgID, d.store.ReadReplica().GetDialect().BooleanStr(false)) + args = append(args, req.OrgID, d.store.GetDialect().BooleanStr(false)) sql := s.String() _, err := sess.SQL(sql, args...).Get(&count) return err @@ -1036,7 +1035,7 @@ func (d *dashboardStore) DeleteDashboardsInFolders( ctx, span := tracer.Start(ctx, "dashboards.database.DeleteDashboardsInFolders") defer span.End() - return d.store.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { + return d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error { // TODO delete all dashboards in the folder in a bulk query for _, folderUID := range req.FolderUIDs { dashboard := dashboards.Dashboard{OrgID: req.OrgID} @@ -1066,7 +1065,7 @@ func (d *dashboardStore) GetAllDashboards(ctx context.Context) ([]*dashboards.Da defer span.End() var dashboards = make([]*dashboards.Dashboard, 0) - err := d.store.ReadReplica().WithDbSession(ctx, func(session *db.Session) error { + err := d.store.WithDbSession(ctx, func(session *db.Session) error { err := session.Find(&dashboards) return err }) @@ -1081,7 +1080,7 @@ func (d *dashboardStore) GetSoftDeletedExpiredDashboards(ctx context.Context, du defer span.End() var dashboards = make([]*dashboards.Dashboard, 0) - err := d.store.DB().WithDbSession(ctx, func(sess *db.Session) error { + err := d.store.WithDbSession(ctx, func(sess *db.Session) error { err := sess.Where("deleted IS NOT NULL AND deleted < ?", time.Now().Add(-duration)).Find(&dashboards) return err }) diff --git a/pkg/services/dashboards/database/database_folder_test.go b/pkg/services/dashboards/database/database_folder_test.go index 6f52c415e55..f654bc428e1 100644 --- a/pkg/services/dashboards/database/database_folder_test.go +++ b/pkg/services/dashboards/database/database_folder_test.go @@ -39,17 +39,17 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { t.Skip("skipping integration test") } t.Run("Testing DB", func(t *testing.T) { - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg var flder, dashInRoot, childDash *dashboards.Dashboard var currentUser *user.SignedInUser var dashboardStore dashboards.Store setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t) + sqlStore, cfg = db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) var err error - dashboardStore, err = ProvideDashboardStore(sqlStore, cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err = ProvideDashboardStore(sqlStore, cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) flder = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, "", true, "prod", "webapp") dashInRoot = insertTestDashboard(t, dashboardStore, "test dash 67", 1, 0, "", false, "prod", "webapp") @@ -68,7 +68,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { t.Run("and user can read folders and dashboards", func(t *testing.T) { currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: []string{dashboards.ScopeDashboardsAll}, dashboards.ActionFoldersRead: []string{dashboards.ScopeFoldersAll}}} - actest.AddUserPermissionToDB(t, sqlStore.DB(), currentUser) + actest.AddUserPermissionToDB(t, sqlStore, currentUser) t.Run("should return all dashboards and folders", func(t *testing.T) { query := &dashboards.FindPersistedDashboardsQuery{ @@ -86,7 +86,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { t.Run("and user can only read dashboards", func(t *testing.T) { currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: []string{dashboards.ScopeDashboardsAll}}} - actest.AddUserPermissionToDB(t, sqlStore.DB(), currentUser) + actest.AddUserPermissionToDB(t, sqlStore, currentUser) t.Run("should not return folder", func(t *testing.T) { query := &dashboards.FindPersistedDashboardsQuery{ @@ -104,7 +104,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { t.Run("and permissions are set for dashboard child and folder has all permissions removed", func(t *testing.T) { currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsProvider.GetResourceScopeUID(dashInRoot.UID)}}} - actest.AddUserPermissionToDB(t, sqlStore.DB(), currentUser) + actest.AddUserPermissionToDB(t, sqlStore, currentUser) t.Run("should not return folder or child", func(t *testing.T) { query := &dashboards.FindPersistedDashboardsQuery{ @@ -119,7 +119,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { t.Run("when the user is given permission to child", func(t *testing.T) { currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsAll}}} - actest.AddUserPermissionToDB(t, sqlStore.DB(), currentUser) + actest.AddUserPermissionToDB(t, sqlStore, currentUser) t.Run("should be able to search for child dashboard but not folder", func(t *testing.T) { query := &dashboards.FindPersistedDashboardsQuery{ @@ -138,17 +138,17 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { }) t.Run("Given two dashboard folders with one dashboard each and one dashboard in the root folder", func(t *testing.T) { - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg var folder1, folder2, dashInRoot, childDash1, childDash2 *dashboards.Dashboard var rootFolderId int64 = 0 var currentUser *user.SignedInUser setup2 := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t) + sqlStore, cfg = db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) var err error - dashboardStore, err = ProvideDashboardStore(sqlStore, cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err = ProvideDashboardStore(sqlStore, cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) folder1 = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, "", true, "prod") folder2 = insertTestDashboard(t, dashboardStore, "2 test dash folder", 1, 0, "", true, "prod") @@ -166,7 +166,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { setup2() t.Run("and one folder is expanded, the other collapsed", func(t *testing.T) { currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsAll}, dashboards.ActionFoldersRead: []string{dashboards.ScopeFoldersAll}}} - actest.AddUserPermissionToDB(t, sqlStore.DB(), currentUser) + actest.AddUserPermissionToDB(t, sqlStore, currentUser) t.Run("should return dashboards in root and expanded folder", func(t *testing.T) { query := &dashboards.FindPersistedDashboardsQuery{ @@ -191,7 +191,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { t.Run("and a dashboard is moved from folder without acl to the folder with an acl", func(t *testing.T) { moveDashboard(t, dashboardStore, 1, childDash2.Data, folder1.ID, folder1.UID) currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: {dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder2.UID), dashboards.ScopeDashboardsProvider.GetResourceScopeUID(dashInRoot.UID)}}} - actest.AddUserPermissionToDB(t, sqlStore.DB(), currentUser) + actest.AddUserPermissionToDB(t, sqlStore, currentUser) t.Run("should not return folder with acl or its children", func(t *testing.T) { query := &dashboards.FindPersistedDashboardsQuery{ @@ -210,7 +210,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { setup2() moveDashboard(t, dashboardStore, 1, childDash1.Data, folder2.ID, childDash2.FolderUID) currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsProvider.GetResourceScopeUID(dashInRoot.UID), dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder2.UID)}, dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder2.UID)}}} - actest.AddUserPermissionToDB(t, sqlStore.DB(), currentUser) + actest.AddUserPermissionToDB(t, sqlStore, currentUser) t.Run("should return folder without acl and its children", func(t *testing.T) { query := &dashboards.FindPersistedDashboardsQuery{ @@ -240,7 +240,7 @@ func TestIntegrationDashboardInheritedFolderRBAC(t *testing.T) { // the maximux nested folder hierarchy starting from parent down to subfolders nestedFolders := make([]*folder.Folder, 0, folder.MaxNestedFolderDepth+1) - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg const ( dashInRootTitle = "dashboard in root" @@ -250,7 +250,7 @@ func TestIntegrationDashboardInheritedFolderRBAC(t *testing.T) { var viewer *user.SignedInUser setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t) + sqlStore, cfg = db.InitTestDBWithCfg(t) cfg.AutoAssignOrg = true cfg.AutoAssignOrgId = 1 cfg.AutoAssignOrgRole = string(org.RoleViewer) @@ -262,13 +262,13 @@ func TestIntegrationDashboardInheritedFolderRBAC(t *testing.T) { features := featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders) var err error - dashboardWriteStore, err := ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardWriteStore, err := ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) - orgService, err := orgimpl.ProvideService(sqlStore.DB(), cfg, quotaService) + orgService, err := orgimpl.ProvideService(sqlStore, cfg, quotaService) require.NoError(t, err) usrSvc, err := userimpl.ProvideService( - sqlStore.DB(), orgService, cfg, nil, nil, tracer, + sqlStore, orgService, cfg, nil, nil, tracer, quotaService, supportbundlestest.NewFakeBundleService(), ) require.NoError(t, err) @@ -303,7 +303,7 @@ func TestIntegrationDashboardInheritedFolderRBAC(t *testing.T) { guardian.New = origNewGuardian }) - folderSvc := folderimpl.ProvideService(mock.New(), bus.ProvideBus(tracer), dashboardWriteStore, folderimpl.ProvideDashboardFolderStore(sqlStore.DB()), sqlStore.DB(), features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + folderSvc := folderimpl.ProvideService(mock.New(), bus.ProvideBus(tracer), dashboardWriteStore, folderimpl.ProvideDashboardFolderStore(sqlStore), sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) parentUID := "" for i := 0; ; i++ { @@ -405,11 +405,11 @@ func TestIntegrationDashboardInheritedFolderRBAC(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - dashboardReadStore, err := ProvideDashboardStore(sqlStore, cfg, tc.features, tagimpl.ProvideService(sqlStore.DB()), quotatest.New(false, nil)) + dashboardReadStore, err := ProvideDashboardStore(sqlStore, cfg, tc.features, tagimpl.ProvideService(sqlStore), quotatest.New(false, nil)) require.NoError(t, err) viewer.Permissions = map[int64]map[string][]string{viewer.OrgID: tc.permissions} - actest.AddUserPermissionToDB(t, sqlStore.DB(), viewer) + actest.AddUserPermissionToDB(t, sqlStore, viewer) query := &dashboards.FindPersistedDashboardsQuery{ SignedInUser: viewer, diff --git a/pkg/services/dashboards/database/database_provisioning_test.go b/pkg/services/dashboards/database/database_provisioning_test.go index 12cbe8aa4ea..798368370e9 100644 --- a/pkg/services/dashboards/database/database_provisioning_test.go +++ b/pkg/services/dashboards/database/database_provisioning_test.go @@ -18,7 +18,7 @@ func TestIntegrationDashboardProvisioningTest(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - sqlStore, cfg := db.InitTestReplDBWithCfg(t) + sqlStore, cfg := db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) dashboardStore, err := ProvideDashboardStore(sqlStore, cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) diff --git a/pkg/services/dashboards/database/database_test.go b/pkg/services/dashboards/database/database_test.go index 0e77bfee2d5..83c118d6047 100644 --- a/pkg/services/dashboards/database/database_test.go +++ b/pkg/services/dashboards/database/database_test.go @@ -44,16 +44,16 @@ func TestIntegrationDashboardDataAccess(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg var savedFolder, savedDash, savedDash2 *dashboards.Dashboard var dashboardStore dashboards.Store setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t) + sqlStore, cfg = db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) var err error - dashboardStore, err = ProvideDashboardStore(sqlStore, cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err = ProvideDashboardStore(sqlStore, cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) // insertTestDashboard creates the following hierarchy: // 1 test dash folder @@ -539,16 +539,16 @@ func TestIntegrationGetSoftDeletedDashboard(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - var sqlStore db.ReplDB + var sqlStore *sqlstore.SQLStore var cfg *setting.Cfg var savedFolder, savedDash *dashboards.Dashboard var dashboardStore dashboards.Store setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t) + sqlStore, cfg = db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) var err error - dashboardStore, err = ProvideDashboardStore(sqlStore, cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err = ProvideDashboardStore(sqlStore, cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) savedFolder = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, "", true, "prod", "webapp") savedDash = insertTestDashboard(t, dashboardStore, "test dash 23", 1, savedFolder.ID, savedFolder.UID, false, "prod", "webapp") @@ -660,7 +660,7 @@ func TestIntegrationDashboardDataAccessGivenPluginWithImportedDashboards(t *test if testing.Short() { t.Skip("skipping integration test") } - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) quotaService := quotatest.New(false, nil) dashboardStore, err := ProvideDashboardStore(sqlStore, &setting.Cfg{}, testFeatureToggles, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) @@ -685,7 +685,7 @@ func TestIntegrationDashboard_SortingOptions(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) quotaService := quotatest.New(false, nil) dashboardStore, err := ProvideDashboardStore(sqlStore, &setting.Cfg{}, testFeatureToggles, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) @@ -736,7 +736,7 @@ func TestIntegrationDashboard_Filter(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() quotaService := quotatest.New(false, nil) dashboardStore, err := ProvideDashboardStore(sqlStore, cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore), quotaService) @@ -780,7 +780,7 @@ func TestIntegrationDashboard_Filter(t *testing.T) { } func TestGetExistingDashboardByTitleAndFolder(t *testing.T) { - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() quotaService := quotatest.New(false, nil) dashboardStore, err := ProvideDashboardStore(sqlStore, cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore), quotaService) @@ -818,7 +818,7 @@ func TestIntegrationFindDashboardsByTitle(t *testing.T) { t.Skip("skipping integration test") } - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() quotaService := quotatest.New(false, nil) features := featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPanelTitleSearch) @@ -936,7 +936,7 @@ func TestIntegrationFindDashboardsByFolder(t *testing.T) { t.Skip("skipping integration test") } - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() quotaService := quotatest.New(false, nil) features := featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPanelTitleSearch) @@ -1118,8 +1118,8 @@ func TestIntegrationFindDashboardsByFolder(t *testing.T) { } } -func insertTestRule(t *testing.T, sqlStore db.ReplDB, foderOrgID int64, folderUID string) { - err := sqlStore.DB().WithDbSession(context.Background(), func(sess *db.Session) error { +func insertTestRule(t *testing.T, sqlStore db.DB, foderOrgID int64, folderUID string) { + err := sqlStore.WithDbSession(context.Background(), func(sess *db.Session) error { type alertQuery struct { RefID string DatasourceUID string diff --git a/pkg/services/dashboards/service/dashboard_service.go b/pkg/services/dashboards/service/dashboard_service.go index 99f68aa917b..34c400461c4 100644 --- a/pkg/services/dashboards/service/dashboard_service.go +++ b/pkg/services/dashboards/service/dashboard_service.go @@ -11,6 +11,7 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" "github.com/prometheus/client_golang/prometheus" "go.opentelemetry.io/otel" + "golang.org/x/exp/slices" "github.com/grafana/grafana/pkg/apimachinery/identity" diff --git a/pkg/services/dashboards/service/dashboard_service_integration_test.go b/pkg/services/dashboards/service/dashboard_service_integration_test.go index e536a332ea5..c1fb4f426a0 100644 --- a/pkg/services/dashboards/service/dashboard_service_integration_test.go +++ b/pkg/services/dashboards/service/dashboard_service_integration_test.go @@ -103,7 +103,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) { permissionScenario(t, "When creating a new dashboard in the General folder", canSave, func(t *testing.T, sc *permissionScenarioContext) { - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cmd := dashboards.SaveDashboardCommand{ OrgID: testOrgID, Dashboard: simplejson.NewFromAny(map[string]any{ @@ -838,7 +838,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) { type permissionScenarioContext struct { dashboardGuardianMock *guardian.FakeDashboardGuardian - sqlStore db.ReplDB + sqlStore db.DB dashboardStore dashboards.Store savedFolder *dashboards.Dashboard savedDashInFolder *dashboards.Dashboard @@ -858,7 +858,7 @@ func permissionScenario(t *testing.T, desc string, canSave bool, fn permissionSc t.Run(desc, func(t *testing.T) { features := featuremgmt.WithFeatures() cfg := setting.NewCfg() - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) quotaService := quotatest.New(false, nil) ac := actest.FakeAccessControl{ExpectedEvaluate: true} dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore), quotaService) @@ -917,16 +917,16 @@ func permissionScenario(t *testing.T, desc string, canSave bool, fn permissionSc }) } -func callSaveWithResult(t *testing.T, cmd dashboards.SaveDashboardCommand, sqlStore db.ReplDB) *dashboards.Dashboard { +func callSaveWithResult(t *testing.T, cmd dashboards.SaveDashboardCommand, sqlStore db.DB) *dashboards.Dashboard { t.Helper() features := featuremgmt.WithFeatures() dto := toSaveDashboardDto(cmd) cfg := setting.NewCfg() quotaService := quotatest.New(false, nil) - dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) - folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore.DB()) + folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) folderPermissions := accesscontrolmock.NewMockedPermissionsService() folderPermissions.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil) @@ -948,14 +948,14 @@ func callSaveWithResult(t *testing.T, cmd dashboards.SaveDashboardCommand, sqlSt return res } -func callSaveWithError(t *testing.T, cmd dashboards.SaveDashboardCommand, sqlStore db.ReplDB) error { +func callSaveWithError(t *testing.T, cmd dashboards.SaveDashboardCommand, sqlStore db.DB) error { features := featuremgmt.WithFeatures() dto := toSaveDashboardDto(cmd) cfg := setting.NewCfg() quotaService := quotatest.New(false, nil) - dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) - folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore.DB()) + folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) service, err := ProvideDashboardServiceImpl( cfg, dashboardStore, folderStore, featuremgmt.WithFeatures(), @@ -970,7 +970,7 @@ func callSaveWithError(t *testing.T, cmd dashboards.SaveDashboardCommand, sqlSto return err } -func saveTestDashboard(t *testing.T, title string, orgID int64, folderUID string, sqlStore db.ReplDB) *dashboards.Dashboard { +func saveTestDashboard(t *testing.T, title string, orgID int64, folderUID string, sqlStore db.DB) *dashboards.Dashboard { t.Helper() cmd := dashboards.SaveDashboardCommand{ @@ -994,9 +994,9 @@ func saveTestDashboard(t *testing.T, title string, orgID int64, folderUID string features := featuremgmt.WithFeatures() cfg := setting.NewCfg() quotaService := quotatest.New(false, nil) - dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) - folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore.DB()) + folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) dashboardPermissions := accesscontrolmock.NewMockedPermissionsService() dashboardPermissions.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil) service, err := ProvideDashboardServiceImpl( @@ -1016,7 +1016,7 @@ func saveTestDashboard(t *testing.T, title string, orgID int64, folderUID string return res } -func saveTestFolder(t *testing.T, title string, orgID int64, sqlStore db.ReplDB) *dashboards.Dashboard { +func saveTestFolder(t *testing.T, title string, orgID int64, sqlStore db.DB) *dashboards.Dashboard { t.Helper() cmd := dashboards.SaveDashboardCommand{ OrgID: orgID, @@ -1044,9 +1044,9 @@ func saveTestFolder(t *testing.T, title string, orgID int64, sqlStore db.ReplDB) features := featuremgmt.WithFeatures() cfg := setting.NewCfg() quotaService := quotatest.New(false, nil) - dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) - folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore.DB()) + folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) folderPermissions := accesscontrolmock.NewMockedPermissionsService() folderPermissions.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil) service, err := ProvideDashboardServiceImpl( diff --git a/pkg/services/dashboardsnapshots/service/service_test.go b/pkg/services/dashboardsnapshots/service/service_test.go index 0c56c52ebd5..c2cdf73efad 100644 --- a/pkg/services/dashboardsnapshots/service/service_test.go +++ b/pkg/services/dashboardsnapshots/service/service_test.go @@ -92,7 +92,7 @@ func TestDashboardSnapshotsService(t *testing.T) { } func TestValidateDashboardExists(t *testing.T) { - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() dsStore := dashsnapdb.ProvideStore(sqlStore, cfg) secretsService := secretsManager.SetupTestService(t, database.ProvideSecretsStore(sqlStore)) diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index 7909994201f..cafad0f1346 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -1324,13 +1324,6 @@ var ( Stage: FeatureStageExperimental, Owner: grafanaPluginsPlatformSquad, }, - { - Name: "databaseReadReplica", - Description: "Use a read replica for some database queries.", - Stage: FeatureStageExperimental, - Owner: grafanaBackendServicesSquad, - Expression: "false", // enabled by default - }, { Name: "zanzana", Description: "Use openFGA as authorization engine.", diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index d05dfd61e64..8cafcf6844f 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -174,7 +174,6 @@ authZGRPCServer,experimental,@grafana/identity-access-team,false,false,false openSearchBackendFlowEnabled,GA,@grafana/aws-datasources,false,false,false ssoSettingsLDAP,experimental,@grafana/identity-access-team,false,false,false failWrongDSUID,experimental,@grafana/plugins-platform-backend,false,false,false -databaseReadReplica,experimental,@grafana/grafana-backend-services-squad,false,false,false zanzana,experimental,@grafana/identity-access-team,false,false,false passScopeToDashboardApi,experimental,@grafana/dashboards-squad,false,false,false alertingApiServer,experimental,@grafana/alerting-squad,false,true,false diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index ae8f0c3d4e5..f32b5c65dca 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -707,10 +707,6 @@ const ( // Throws an error if a datasource has an invalid UIDs FlagFailWrongDSUID = "failWrongDSUID" - // FlagDatabaseReadReplica - // Use a read replica for some database queries. - FlagDatabaseReadReplica = "databaseReadReplica" - // FlagZanzana // Use openFGA as authorization engine. FlagZanzana = "zanzana" diff --git a/pkg/services/featuremgmt/toggles_gen.json b/pkg/services/featuremgmt/toggles_gen.json index f1f8041c5b5..9a2acd079e6 100644 --- a/pkg/services/featuremgmt/toggles_gen.json +++ b/pkg/services/featuremgmt/toggles_gen.json @@ -869,6 +869,7 @@ "name": "databaseReadReplica", "resourceVersion": "1720021873452", "creationTimestamp": "2024-06-18T15:07:15Z", + "deletionTimestamp": "2024-09-20T20:03:26Z", "annotations": { "grafana.app/updatedTimestamp": "2024-07-03 15:51:13.452477 +0000 UTC" } diff --git a/pkg/services/folder/folderimpl/dashboard_folder_store_test.go b/pkg/services/folder/folderimpl/dashboard_folder_store_test.go index 660fdeb40ec..8345f6ce32a 100644 --- a/pkg/services/folder/folderimpl/dashboard_folder_store_test.go +++ b/pkg/services/folder/folderimpl/dashboard_folder_store_test.go @@ -23,15 +23,15 @@ func TestMain(m *testing.M) { } func TestIntegrationDashboardFolderStore(t *testing.T) { - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg var dashboardStore dashboards.Store setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t) + sqlStore, cfg = db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) var err error - dashboardStore, err = database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(featuremgmt.FlagPanelTitleSearch), tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err = database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(featuremgmt.FlagPanelTitleSearch), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) } t.Run("Given dashboard and folder with the same title", func(t *testing.T) { diff --git a/pkg/services/folder/folderimpl/folder_test.go b/pkg/services/folder/folderimpl/folder_test.go index f2712ff2359..7ad8b4b8235 100644 --- a/pkg/services/folder/folderimpl/folder_test.go +++ b/pkg/services/folder/folderimpl/folder_test.go @@ -418,7 +418,7 @@ func TestIntegrationNestedFolderService(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - db, cfg := sqlstore.InitTestReplDB(t) + db, cfg := sqlstore.InitTestDB(t) cfg.UnifiedAlerting.BaseInterval = time.Second quotaService := quotatest.New(false, nil) folderStore := ProvideDashboardFolderStore(db) @@ -828,7 +828,7 @@ func TestFolderServiceDualWrite(t *testing.T) { guardian.New = g }) - db, _ := sqlstore.InitTestReplDB(t) + db, _ := sqlstore.InitTestDB(t) cfg := setting.NewCfg() features := featuremgmt.WithFeatures() nestedFolderStore := ProvideStore(db) @@ -1459,7 +1459,7 @@ func TestIntegrationNestedFolderSharedWithMe(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - db, cfg := sqlstore.InitTestReplDB(t) + db, cfg := sqlstore.InitTestDB(t) quotaService := quotatest.New(false, nil) folderStore := ProvideDashboardFolderStore(db) @@ -1863,7 +1863,7 @@ func TestIntegrationNestedFolderSharedWithMe(t *testing.T) { } func TestFolderServiceGetFolder(t *testing.T) { - db, _ := sqlstore.InitTestReplDB(t) + db, _ := sqlstore.InitTestDB(t) signedInAdminUser := user.SignedInUser{UserID: 1, OrgID: orgID, Permissions: map[int64]map[string][]string{ orgID: { @@ -1962,7 +1962,7 @@ func TestFolderServiceGetFolder(t *testing.T) { } func TestFolderServiceGetFolders(t *testing.T) { - db, cfg := sqlstore.InitTestReplDB(t) + db, cfg := sqlstore.InitTestDB(t) quotaService := quotatest.New(false, nil) folderStore := ProvideDashboardFolderStore(db) @@ -2038,7 +2038,7 @@ func TestFolderServiceGetFolders(t *testing.T) { // TODO replace it with an API test under /pkg/tests/api/folders // whenever the golang client with get updated to allow filtering child folders by permission func TestGetChildrenFilterByPermission(t *testing.T) { - db, cfg := sqlstore.InitTestReplDB(t) + db, cfg := sqlstore.InitTestDB(t) signedInAdminUser := user.SignedInUser{UserID: 1, OrgID: orgID, Permissions: map[int64]map[string][]string{ orgID: { diff --git a/pkg/services/libraryelements/libraryelements_delete_test.go b/pkg/services/libraryelements/libraryelements_delete_test.go index c09062b18a4..597787d6ee0 100644 --- a/pkg/services/libraryelements/libraryelements_delete_test.go +++ b/pkg/services/libraryelements/libraryelements_delete_test.go @@ -4,13 +4,12 @@ import ( "encoding/json" "testing" - "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/libraryelements/model" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/web" + "github.com/stretchr/testify/require" ) func TestDeleteLibraryElement(t *testing.T) { @@ -75,7 +74,7 @@ func TestDeleteLibraryElement(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } // nolint:staticcheck - dashInDB := createDashboard(t, sc.replStore, sc.user, &dash, sc.folder.ID, sc.folder.UID) + dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.ID, sc.folder.UID) err := sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{sc.initialResult.Result.UID}, dashInDB.ID) require.NoError(t, err) diff --git a/pkg/services/libraryelements/libraryelements_get_test.go b/pkg/services/libraryelements/libraryelements_get_test.go index 869e326389b..b441505639b 100644 --- a/pkg/services/libraryelements/libraryelements_get_test.go +++ b/pkg/services/libraryelements/libraryelements_get_test.go @@ -4,14 +4,13 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/kinds/librarypanel" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/libraryelements/model" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/web" + "github.com/stretchr/testify/require" ) func TestGetLibraryElement(t *testing.T) { @@ -125,7 +124,7 @@ func TestGetLibraryElement(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } // nolint:staticcheck - dashInDB := createDashboard(t, sc.replStore, sc.user, &dash, sc.folder.ID, sc.folder.UID) + dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.ID, sc.folder.UID) err := sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{sc.initialResult.Result.UID}, dashInDB.ID) require.NoError(t, err) diff --git a/pkg/services/libraryelements/libraryelements_test.go b/pkg/services/libraryelements/libraryelements_test.go index 9937ceb6aae..1f5c22168ff 100644 --- a/pkg/services/libraryelements/libraryelements_test.go +++ b/pkg/services/libraryelements/libraryelements_test.go @@ -89,7 +89,7 @@ func TestDeleteLibraryPanelsInFolder(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } // nolint:staticcheck - dashInDB := createDashboard(t, sc.replStore, sc.user, &dash, sc.folder.ID, sc.folder.UID) + dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.ID, sc.folder.UID) err := sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{sc.initialResult.Result.UID}, dashInDB.ID) require.NoError(t, err) @@ -164,7 +164,7 @@ func TestGetLibraryPanelConnections(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } // nolint:staticcheck - dashInDB := createDashboard(t, sc.replStore, sc.user, &dash, sc.folder.ID, sc.folder.UID) + dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.ID, sc.folder.UID) err := sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{sc.initialResult.Result.UID}, dashInDB.ID) require.NoError(t, err) @@ -279,11 +279,10 @@ type scenarioContext struct { folder *folder.Folder initialResult libraryElementResult sqlStore db.DB - replStore db.ReplDB log log.Logger } -func createDashboard(t *testing.T, sqlStore db.ReplDB, user user.SignedInUser, dash *dashboards.Dashboard, folderID int64, folderUID string) *dashboards.Dashboard { +func createDashboard(t *testing.T, sqlStore db.DB, user user.SignedInUser, dash *dashboards.Dashboard, folderID int64, folderUID string) *dashboards.Dashboard { // nolint:staticcheck dash.FolderID = folderID dash.FolderUID = folderUID @@ -298,13 +297,13 @@ func createDashboard(t *testing.T, sqlStore db.ReplDB, user user.SignedInUser, d features := featuremgmt.WithFeatures() cfg := setting.NewCfg() quotaService := quotatest.New(false, nil) - dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) ac := actest.FakeAccessControl{ExpectedEvaluate: true} folderPermissions := acmock.NewMockedPermissionsService() dashboardPermissions := acmock.NewMockedPermissionsService() dashboardPermissions.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil) - folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore.DB()) + folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) service, err := dashboardservice.ProvideDashboardServiceImpl( cfg, dashboardStore, folderStore, features, folderPermissions, dashboardPermissions, ac, @@ -325,7 +324,7 @@ func createFolder(t *testing.T, sc scenarioContext, title string) *folder.Folder cfg := setting.NewCfg() ac := actest.FakeAccessControl{ExpectedEvaluate: true} quotaService := quotatest.New(false, nil) - dashboardStore, err := database.ProvideDashboardStore(sc.replStore, cfg, features, tagimpl.ProvideService(sc.sqlStore), quotaService) + dashboardStore, err := database.ProvideDashboardStore(sc.sqlStore, cfg, features, tagimpl.ProvideService(sc.sqlStore), quotaService) require.NoError(t, err) folderStore := folderimpl.ProvideDashboardFolderStore(sc.sqlStore) @@ -381,7 +380,7 @@ func scenarioWithPanel(t *testing.T, desc string, fn func(t *testing.T, sc scena t.Helper() features := featuremgmt.WithFeatures() - sqlStore, cfg := db.InitTestReplDBWithCfg(t) + sqlStore, cfg := db.InitTestDBWithCfg(t) ac := actest.FakeAccessControl{} quotaService := quotatest.New(false, nil) dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore), quotaService) @@ -442,7 +441,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo features := featuremgmt.WithFeatures() tracer := tracing.InitializeTracerForTest() - sqlStore, cfg := db.InitTestReplDBWithCfg(t) + sqlStore, cfg := db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) @@ -485,11 +484,10 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo require.NoError(t, err) sc := scenarioContext{ - user: usr, - ctx: &webCtx, - service: &service, - sqlStore: sqlStore.DB(), - replStore: sqlStore, + user: usr, + ctx: &webCtx, + service: &service, + sqlStore: sqlStore, reqContext: &contextmodel.ReqContext{ Context: &webCtx, SignedInUser: &usr, diff --git a/pkg/services/librarypanels/librarypanels_test.go b/pkg/services/librarypanels/librarypanels_test.go index a5389988491..89bcb12b3cb 100644 --- a/pkg/services/librarypanels/librarypanels_test.go +++ b/pkg/services/librarypanels/librarypanels_test.go @@ -84,7 +84,7 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) { Title: "Testing ConnectLibraryPanelsForDashboard", Data: simplejson.NewFromAny(dashJSON), } - dashInDB := createDashboard(t, sc.replStore, sc.user, &dash) + dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash) err := sc.service.ConnectLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB) require.NoError(t, err) @@ -182,7 +182,7 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) { Title: "Testing ConnectLibraryPanelsForDashboard", Data: simplejson.NewFromAny(dashJSON), } - dashInDB := createDashboard(t, sc.replStore, sc.user, &dash) + dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash) err = sc.service.ConnectLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB) require.NoError(t, err) @@ -228,7 +228,7 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) { Title: "Testing ConnectLibraryPanelsForDashboard", Data: simplejson.NewFromAny(dashJSON), } - dashInDB := createDashboard(t, sc.replStore, sc.user, &dash) + dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash) err := sc.service.ConnectLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB) require.EqualError(t, err, errLibraryPanelHeaderUIDMissing.Error()) @@ -284,7 +284,7 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) { Title: "Testing ConnectLibraryPanelsForDashboard", Data: simplejson.NewFromAny(dashJSON), } - dashInDB := createDashboard(t, sc.replStore, sc.user, &dash) + dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash) err = sc.elementService.ConnectElementsToDashboard(sc.ctx, sc.user, []string{sc.initialResult.Result.UID}, dashInDB.ID) require.NoError(t, err) @@ -635,7 +635,6 @@ type scenarioContext struct { folder *folder.Folder initialResult libraryPanelResult sqlStore db.DB - replStore db.ReplDB lps LibraryPanelService } @@ -712,7 +711,7 @@ func getExpected(t *testing.T, res model.LibraryElementDTO, UID string, name str } } -func createDashboard(t *testing.T, sqlStore db.ReplDB, user *user.SignedInUser, dash *dashboards.Dashboard) *dashboards.Dashboard { +func createDashboard(t *testing.T, sqlStore db.DB, user *user.SignedInUser, dash *dashboards.Dashboard) *dashboards.Dashboard { dashItem := &dashboards.SaveDashboardDTO{ Dashboard: dash, Message: "", @@ -724,10 +723,10 @@ func createDashboard(t *testing.T, sqlStore db.ReplDB, user *user.SignedInUser, features := featuremgmt.WithFeatures() cfg := setting.NewCfg() quotaService := quotatest.New(false, nil) - dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) ac := actest.FakeAccessControl{ExpectedEvaluate: true} - folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore.DB()) + folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) dashPermissionService := acmock.NewMockedPermissionsService() dashPermissionService.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil) service, err := dashboardservice.ProvideDashboardServiceImpl( @@ -750,7 +749,7 @@ func createFolder(t *testing.T, sc scenarioContext, title string) *folder.Folder ac := actest.FakeAccessControl{ExpectedEvaluate: true} cfg := setting.NewCfg() quotaService := quotatest.New(false, nil) - dashboardStore, err := database.ProvideDashboardStore(sc.replStore, cfg, features, tagimpl.ProvideService(sc.sqlStore), quotaService) + dashboardStore, err := database.ProvideDashboardStore(sc.sqlStore, cfg, features, tagimpl.ProvideService(sc.sqlStore), quotaService) require.NoError(t, err) folderStore := folderimpl.ProvideDashboardFolderStore(sc.sqlStore) s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sc.sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) @@ -815,8 +814,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo t.Run(desc, func(t *testing.T) { orgID := int64(1) role := org.RoleAdmin - replStore, cfg := db.InitTestReplDBWithCfg(t) - sqlStore := replStore.DB() + sqlStore, cfg := db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) ac := actest.FakeAccessControl{ExpectedEvaluate: true} @@ -833,7 +831,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo require.NoError(t, err) guardian.InitAccessControlGuardian(setting.NewCfg(), ac, dashService) - dashboardStore, err := database.ProvideDashboardStore(replStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) + dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) features := featuremgmt.WithFeatures() folderService := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) @@ -886,7 +884,6 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo service: &service, elementService: elementService, sqlStore: sqlStore, - replStore: replStore, lps: service, } diff --git a/pkg/services/ngalert/api/api_provisioning_test.go b/pkg/services/ngalert/api/api_provisioning_test.go index 785d433769f..32fa6c7d460 100644 --- a/pkg/services/ngalert/api/api_provisioning_test.go +++ b/pkg/services/ngalert/api/api_provisioning_test.go @@ -1793,8 +1793,7 @@ func createTestEnv(t *testing.T, testConfig string) testEnvironment { GetsConfig(models.AlertConfiguration{ AlertmanagerConfiguration: string(raw), }) - replDB, cfg := db.InitTestReplDBWithCfg(t) - sqlStore := replDB.DB() + sqlStore, cfg := db.InitTestDBWithCfg(t) quotas := &provisioning.MockQuotaChecker{} quotas.EXPECT().LimitOK() @@ -1818,7 +1817,7 @@ func createTestEnv(t *testing.T, testConfig string) testEnvironment { }}, nil).Maybe() ac := &recordingAccessControlFake{} - dashboardStore, err := database.ProvideDashboardStore(replDB, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotatest.New(false, nil)) + dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotatest.New(false, nil)) require.NoError(t, err) folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) diff --git a/pkg/services/ngalert/provisioning/alert_rules_test.go b/pkg/services/ngalert/provisioning/alert_rules_test.go index ed9bf7e3514..e5e819ef45f 100644 --- a/pkg/services/ngalert/provisioning/alert_rules_test.go +++ b/pkg/services/ngalert/provisioning/alert_rules_test.go @@ -16,6 +16,12 @@ import ( "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/expr" + "github.com/grafana/grafana/pkg/services/ngalert/accesscontrol" + "github.com/grafana/grafana/pkg/services/ngalert/tests/fakes" + "github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest" + "github.com/grafana/grafana/pkg/services/user" + "github.com/grafana/grafana/pkg/util" + "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/tracing" @@ -25,15 +31,10 @@ import ( "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/folder/folderimpl" "github.com/grafana/grafana/pkg/services/folder/foldertest" - "github.com/grafana/grafana/pkg/services/ngalert/accesscontrol" "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/grafana/grafana/pkg/services/ngalert/store" - "github.com/grafana/grafana/pkg/services/ngalert/tests/fakes" "github.com/grafana/grafana/pkg/services/ngalert/testutil" - "github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest" - "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" - "github.com/grafana/grafana/pkg/util" ) func TestAlertRuleService(t *testing.T) { @@ -1541,7 +1542,7 @@ func TestDeleteRuleGroup(t *testing.T) { func TestProvisiongWithFullpath(t *testing.T) { tracer := tracing.InitializeTracerForTest() inProcBus := bus.ProvideBus(tracer) - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) _, dashboardStore := testutil.SetupDashboardService(t, sqlStore, folderStore, cfg) diff --git a/pkg/services/ngalert/store/alert_rule_test.go b/pkg/services/ngalert/store/alert_rule_test.go index 8300f0a213f..2969f24d56b 100644 --- a/pkg/services/ngalert/store/alert_rule_test.go +++ b/pkg/services/ngalert/store/alert_rule_test.go @@ -16,21 +16,22 @@ import ( "golang.org/x/exp/rand" "github.com/grafana/grafana/pkg/bus" - "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log/logtest" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/actest" - acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/folder/folderimpl" - "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/grafana/grafana/pkg/services/ngalert/testutil" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/user" + + "github.com/grafana/grafana/pkg/infra/db" + acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" + "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" ) @@ -41,7 +42,7 @@ func TestIntegrationUpdateAlertRules(t *testing.T) { } cfg := setting.NewCfg() cfg.UnifiedAlerting = setting.UnifiedAlertingSettings{BaseInterval: time.Duration(rand.Int63n(100)+1) * time.Second} - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) store := &DBstore{ SQLStore: sqlStore, Cfg: cfg.UnifiedAlerting, @@ -120,7 +121,7 @@ func TestIntegrationUpdateAlertRulesWithUniqueConstraintViolation(t *testing.T) } cfg := setting.NewCfg() cfg.UnifiedAlerting = setting.UnifiedAlertingSettings{BaseInterval: time.Duration(rand.Int63n(100)+1) * time.Second} - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) store := &DBstore{ SQLStore: sqlStore, Cfg: cfg.UnifiedAlerting, @@ -377,7 +378,7 @@ func TestIntegration_GetAlertRulesForScheduling(t *testing.T) { BaseInterval: time.Duration(rand.Int63n(100)) * time.Second, } - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) store := &DBstore{ Logger: &logtest.Fake{}, SQLStore: sqlStore, @@ -501,7 +502,7 @@ func TestIntegration_CountAlertRules(t *testing.T) { t.Skip("skipping integration test") } - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() store := &DBstore{SQLStore: sqlStore, FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())} @@ -566,7 +567,7 @@ func TestIntegration_DeleteInFolder(t *testing.T) { t.Skip("skipping integration test") } - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() store := &DBstore{ SQLStore: sqlStore, @@ -599,7 +600,7 @@ func TestIntegration_GetNamespaceByUID(t *testing.T) { t.Skip("skipping integration test") } - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() store := &DBstore{ SQLStore: sqlStore, @@ -653,7 +654,7 @@ func TestIntegrationInsertAlertRules(t *testing.T) { } orgID := int64(1) - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() cfg.UnifiedAlerting.BaseInterval = 1 * time.Second store := &DBstore{ @@ -804,7 +805,7 @@ func TestIntegrationAlertRulesNotificationSettings(t *testing.T) { return result } - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() cfg.UnifiedAlerting.BaseInterval = 1 * time.Second store := &DBstore{ @@ -1080,7 +1081,7 @@ func TestIntegrationListNotificationSettings(t *testing.T) { t.Skip("skipping integration test") } - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() cfg.UnifiedAlerting.BaseInterval = 1 * time.Second store := &DBstore{ @@ -1203,7 +1204,7 @@ func TestIntegrationGetNamespacesByRuleUID(t *testing.T) { t.Skip("skipping integration test") } - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() cfg.UnifiedAlerting.BaseInterval = 1 * time.Second store := &DBstore{ @@ -1254,7 +1255,7 @@ func TestIntegrationRuleGroupsCaseSensitive(t *testing.T) { t.Skip("skipping integration test") } - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) cfg := setting.NewCfg() cfg.UnifiedAlerting.BaseInterval = 1 * time.Second store := &DBstore{ @@ -1363,7 +1364,7 @@ func TestIncreaseVersionForAllRulesInNamespaces(t *testing.T) { } cfg := setting.NewCfg() cfg.UnifiedAlerting = setting.UnifiedAlertingSettings{BaseInterval: time.Duration(rand.Int63n(100)+1) * time.Second} - sqlStore := db.InitTestReplDB(t) + sqlStore := db.InitTestDB(t) store := &DBstore{ SQLStore: sqlStore, Cfg: cfg.UnifiedAlerting, @@ -1463,11 +1464,11 @@ func createFolder(t *testing.T, store *DBstore, uid, title string, orgID int64, require.NoError(t, err) } -func setupFolderService(t *testing.T, sqlStore db.ReplDB, cfg *setting.Cfg, features featuremgmt.FeatureToggles) folder.Service { +func setupFolderService(t *testing.T, sqlStore db.DB, cfg *setting.Cfg, features featuremgmt.FeatureToggles) folder.Service { tracer := tracing.InitializeTracerForTest() inProcBus := bus.ProvideBus(tracer) - folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore.DB()) + folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) _, dashboardStore := testutil.SetupDashboardService(t, sqlStore, folderStore, cfg) - return testutil.SetupFolderService(t, cfg, sqlStore.DB(), dashboardStore, folderStore, inProcBus, features, &actest.FakeAccessControl{ExpectedEvaluate: true}) + return testutil.SetupFolderService(t, cfg, sqlStore, dashboardStore, folderStore, inProcBus, features, &actest.FakeAccessControl{ExpectedEvaluate: true}) } diff --git a/pkg/services/ngalert/store/testing.go b/pkg/services/ngalert/store/testing.go index 9efa3804f80..39f6f4ffb09 100644 --- a/pkg/services/ngalert/store/testing.go +++ b/pkg/services/ngalert/store/testing.go @@ -7,10 +7,10 @@ import ( "testing" "time" + "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/log/logtest" "github.com/grafana/grafana/pkg/services/folder/foldertest" "github.com/grafana/grafana/pkg/services/ngalert/models" - "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/setting" ) @@ -134,7 +134,7 @@ func (f *FakeAdminConfigStore) UpdateAdminConfiguration(cmd UpdateAdminConfigura return nil } -func SetupStoreForTesting(t *testing.T, db *sqlstore.ReplStore) *DBstore { +func SetupStoreForTesting(t *testing.T, db db.DB) *DBstore { t.Helper() cfg := setting.NewCfg() cfg.UnifiedAlerting = setting.UnifiedAlertingSettings{BaseInterval: 1 * time.Second} diff --git a/pkg/services/ngalert/tests/util.go b/pkg/services/ngalert/tests/util.go index 4b635292ba5..ae5664adeec 100644 --- a/pkg/services/ngalert/tests/util.go +++ b/pkg/services/ngalert/tests/util.go @@ -54,8 +54,7 @@ func SetupTestEnv(tb testing.TB, baseInterval time.Duration) (*ngalert.AlertNG, *cfg.UnifiedAlerting.Enabled = true m := metrics.NewNGAlert(prometheus.NewRegistry()) - replStore := db.InitTestReplDB(tb) - sqlStore := replStore.DB() + sqlStore := db.InitTestDB(tb) secretsService := secretsManager.SetupTestService(tb, database.ProvideSecretsStore(sqlStore)) ac := acmock.New() @@ -63,7 +62,7 @@ func SetupTestEnv(tb testing.TB, baseInterval time.Duration) (*ngalert.AlertNG, tracer := tracing.InitializeTracerForTest() bus := bus.ProvideBus(tracer) folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) - dashboardService, dashboardStore := testutil.SetupDashboardService(tb, replStore, folderStore, cfg) + dashboardService, dashboardStore := testutil.SetupDashboardService(tb, sqlStore, folderStore, cfg) features := featuremgmt.WithFeatures() folderService := testutil.SetupFolderService(tb, cfg, sqlStore, dashboardStore, folderStore, bus, features, ac) ruleStore, err := store.ProvideDBStore(cfg, featuremgmt.WithFeatures(), sqlStore, folderService, &dashboards.FakeDashboardService{}, ac) diff --git a/pkg/services/ngalert/testutil/testutil.go b/pkg/services/ngalert/testutil/testutil.go index a1986de8734..6311a9ffdbb 100644 --- a/pkg/services/ngalert/testutil/testutil.go +++ b/pkg/services/ngalert/testutil/testutil.go @@ -30,7 +30,7 @@ func SetupFolderService(tb testing.TB, cfg *setting.Cfg, db db.DB, dashboardStor return folderimpl.ProvideService(ac, bus, dashboardStore, folderStore, db, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) } -func SetupDashboardService(tb testing.TB, sqlStore db.ReplDB, fs *folderimpl.DashboardFolderStoreImpl, cfg *setting.Cfg) (*dashboardservice.DashboardServiceImpl, dashboards.Store) { +func SetupDashboardService(tb testing.TB, sqlStore db.DB, fs *folderimpl.DashboardFolderStoreImpl, cfg *setting.Cfg) (*dashboardservice.DashboardServiceImpl, dashboards.Store) { tb.Helper() origNewGuardian := guardian.New @@ -51,7 +51,7 @@ func SetupDashboardService(tb testing.TB, sqlStore db.ReplDB, fs *folderimpl.Das features := featuremgmt.WithFeatures() quotaService := quotatest.New(false, nil) - dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(tb, err) dashboardService, err := dashboardservice.ProvideDashboardServiceImpl( diff --git a/pkg/services/org/orgimpl/store_test.go b/pkg/services/org/orgimpl/store_test.go index 72288d14c26..a4f839d6842 100644 --- a/pkg/services/org/orgimpl/store_test.go +++ b/pkg/services/org/orgimpl/store_test.go @@ -906,7 +906,7 @@ func TestIntegration_SQLStore_RemoveOrgUser(t *testing.T) { func createOrgAndUserSvc(t *testing.T, store db.DB, cfg *setting.Cfg) (org.Service, user.Service) { t.Helper() - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(store), cfg) + quotaService := quotaimpl.ProvideService(store, cfg) orgService, err := ProvideService(store, cfg, quotaService) require.NoError(t, err) usrSvc, err := userimpl.ProvideService( diff --git a/pkg/services/publicdashboards/api/query_test.go b/pkg/services/publicdashboards/api/query_test.go index bb6a201c3c4..6146c36de2f 100644 --- a/pkg/services/publicdashboards/api/query_test.go +++ b/pkg/services/publicdashboards/api/query_test.go @@ -254,7 +254,7 @@ func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T) if testing.Short() { t.Skip("skipping integration test") } - db, cfg := db.InitTestReplDBWithCfg(t) + db, cfg := db.InitTestDBWithCfg(t) cacheService := datasourcesService.ProvideCacheService(localcache.ProvideService(), db, guardian.ProvideGuardian()) qds := buildQueryDataService(t, cacheService, nil, db) diff --git a/pkg/services/publicdashboards/database/database_test.go b/pkg/services/publicdashboards/database/database_test.go index 2138e4ccd5f..d2e506063b1 100644 --- a/pkg/services/publicdashboards/database/database_test.go +++ b/pkg/services/publicdashboards/database/database_test.go @@ -48,7 +48,6 @@ func TestIntegrationListPublicDashboard(t *testing.T) { } var sqlStore db.DB - var replStore db.ReplDB var cfg *setting.Cfg var aDash *dashboards.Dashboard @@ -64,10 +63,9 @@ func TestIntegrationListPublicDashboard(t *testing.T) { var publicdashboardStore *PublicDashboardStoreImpl setup := func() { - replStore, cfg = db.InitTestReplDBWithCfg(t, db.InitTestDBOpt{}) - sqlStore = replStore.DB() + sqlStore, cfg = db.InitTestDBWithCfg(t, db.InitTestDBOpt{}) quotaService := quotatest.New(false, nil) - dashboardStore, err := dashboardsDB.ProvideDashboardStore(replStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) publicdashboardStore = ProvideStore(sqlStore, cfg, featuremgmt.WithFeatures()) @@ -173,19 +171,19 @@ func TestIntegrationExistsEnabledByAccessToken(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg var dashboardStore dashboards.Store var publicdashboardStore *PublicDashboardStoreImpl var savedDashboard *dashboards.Dashboard setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t) + sqlStore, cfg = db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) - store, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + store, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) dashboardStore = store - publicdashboardStore = ProvideStore(sqlStore.DB(), cfg, featuremgmt.WithFeatures()) + publicdashboardStore = ProvideStore(sqlStore, cfg, featuremgmt.WithFeatures()) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, "", true) } t.Run("ExistsEnabledByAccessToken will return true when at least one public dashboard has a matching access token", func(t *testing.T) { @@ -246,19 +244,19 @@ func TestIntegrationExistsEnabledByDashboardUid(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg var dashboardStore dashboards.Store var publicdashboardStore *PublicDashboardStoreImpl var savedDashboard *dashboards.Dashboard setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t) + sqlStore, cfg = db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) - store, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + store, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) dashboardStore = store - publicdashboardStore = ProvideStore(sqlStore.DB(), cfg, featuremgmt.WithFeatures()) + publicdashboardStore = ProvideStore(sqlStore, cfg, featuremgmt.WithFeatures()) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, "", true) } @@ -311,19 +309,19 @@ func TestIntegrationFindByDashboardUid(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg var dashboardStore dashboards.Store var publicdashboardStore *PublicDashboardStoreImpl var savedDashboard *dashboards.Dashboard setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t) + sqlStore, cfg = db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) - store, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + store, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) dashboardStore = store - publicdashboardStore = ProvideStore(sqlStore.DB(), cfg, featuremgmt.WithFeatures()) + publicdashboardStore = ProvideStore(sqlStore, cfg, featuremgmt.WithFeatures()) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, "", true) } @@ -379,7 +377,7 @@ func TestIntegrationFindByAccessToken(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg var dashboardStore dashboards.Store var publicdashboardStore *PublicDashboardStoreImpl @@ -387,10 +385,10 @@ func TestIntegrationFindByAccessToken(t *testing.T) { var err error setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t) - dashboardStore, err = dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotatest.New(false, nil)) + sqlStore, cfg = db.InitTestDBWithCfg(t) + dashboardStore, err = dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotatest.New(false, nil)) require.NoError(t, err) - publicdashboardStore = ProvideStore(sqlStore.DB(), cfg, featuremgmt.WithFeatures()) + publicdashboardStore = ProvideStore(sqlStore, cfg, featuremgmt.WithFeatures()) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, "", true) } @@ -447,7 +445,7 @@ func TestIntegrationCreatePublicDashboard(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg var dashboardStore dashboards.Store var publicdashboardStore *PublicDashboardStoreImpl @@ -455,12 +453,12 @@ func TestIntegrationCreatePublicDashboard(t *testing.T) { var savedDashboard2 *dashboards.Dashboard setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t, db.InitTestDBOpt{}) + sqlStore, cfg = db.InitTestDBWithCfg(t, db.InitTestDBOpt{}) quotaService := quotatest.New(false, nil) - store, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + store, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) dashboardStore = store - publicdashboardStore = ProvideStore(sqlStore.DB(), cfg, featuremgmt.WithFeatures()) + publicdashboardStore = ProvideStore(sqlStore, cfg, featuremgmt.WithFeatures()) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, "", true) savedDashboard2 = insertTestDashboard(t, dashboardStore, "testDashie2", 1, "", true) insertPublicDashboard(t, publicdashboardStore, savedDashboard2.UID, savedDashboard2.OrgID, false, PublicShareType) @@ -526,7 +524,7 @@ func TestIntegrationUpdatePublicDashboard(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg var dashboardStore dashboards.Store var publicdashboardStore *PublicDashboardStoreImpl @@ -535,11 +533,11 @@ func TestIntegrationUpdatePublicDashboard(t *testing.T) { var err error setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t, db.InitTestDBOpt{}) + sqlStore, cfg = db.InitTestDBWithCfg(t, db.InitTestDBOpt{}) quotaService := quotatest.New(false, nil) - dashboardStore, err = dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err = dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) - publicdashboardStore = ProvideStore(sqlStore.DB(), cfg, featuremgmt.WithFeatures()) + publicdashboardStore = ProvideStore(sqlStore, cfg, featuremgmt.WithFeatures()) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, "", true) anotherSavedDashboard = insertTestDashboard(t, dashboardStore, "test another Dashie", 1, "", true) } @@ -631,7 +629,7 @@ func TestIntegrationGetOrgIdByAccessToken(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg var dashboardStore dashboards.Store var publicdashboardStore *PublicDashboardStoreImpl @@ -639,11 +637,11 @@ func TestIntegrationGetOrgIdByAccessToken(t *testing.T) { var err error setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t) + sqlStore, cfg = db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) - dashboardStore, err = dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err = dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) - publicdashboardStore = ProvideStore(sqlStore.DB(), cfg, featuremgmt.WithFeatures()) + publicdashboardStore = ProvideStore(sqlStore, cfg, featuremgmt.WithFeatures()) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, "", true) } t.Run("GetOrgIdByAccessToken will OrgId when enabled", func(t *testing.T) { @@ -703,7 +701,7 @@ func TestIntegrationDelete(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg var dashboardStore dashboards.Store var publicdashboardStore *PublicDashboardStoreImpl @@ -712,10 +710,10 @@ func TestIntegrationDelete(t *testing.T) { var err error setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t) - dashboardStore, err = dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotatest.New(false, nil)) + sqlStore, cfg = db.InitTestDBWithCfg(t) + dashboardStore, err = dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotatest.New(false, nil)) require.NoError(t, err) - publicdashboardStore = ProvideStore(sqlStore.DB(), cfg, featuremgmt.WithFeatures()) + publicdashboardStore = ProvideStore(sqlStore, cfg, featuremgmt.WithFeatures()) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, "", true) savedPublicDashboard = insertPublicDashboard(t, publicdashboardStore, savedDashboard.UID, savedDashboard.OrgID, true, PublicShareType) } @@ -763,7 +761,7 @@ func TestFindByFolder(t *testing.T) { }) t.Run("can get all pubdashes for dashboard folder and org", func(t *testing.T) { - sqlStore, cfg := db.InitTestReplDBWithCfg(t) + sqlStore, cfg := db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) @@ -792,7 +790,7 @@ func TestGetMetrics(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - var sqlStore db.ReplDB + var sqlStore db.DB var cfg *setting.Cfg var dashboardStore dashboards.Store var publicdashboardStore *PublicDashboardStoreImpl @@ -802,12 +800,12 @@ func TestGetMetrics(t *testing.T) { var savedDashboard4 *dashboards.Dashboard setup := func() { - sqlStore, cfg = db.InitTestReplDBWithCfg(t, db.InitTestDBOpt{}) + sqlStore, cfg = db.InitTestDBWithCfg(t, db.InitTestDBOpt{}) quotaService := quotatest.New(false, nil) - store, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + store, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) dashboardStore = store - publicdashboardStore = ProvideStore(sqlStore.DB(), cfg, featuremgmt.WithFeatures()) + publicdashboardStore = ProvideStore(sqlStore, cfg, featuremgmt.WithFeatures()) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, "", false) savedDashboard2 = insertTestDashboard(t, dashboardStore, "testDashie2", 1, "", false) savedDashboard3 = insertTestDashboard(t, dashboardStore, "testDashie3", 2, "", false) diff --git a/pkg/services/publicdashboards/service/common_test.go b/pkg/services/publicdashboards/service/common_test.go index a81fbf32784..fd014362050 100644 --- a/pkg/services/publicdashboards/service/common_test.go +++ b/pkg/services/publicdashboards/service/common_test.go @@ -24,10 +24,10 @@ func newPublicDashboardServiceImpl( publicDashboardStore publicdashboards.Store, dashboardService dashboards.DashboardService, annotationsRepo annotations.Repository, -) (*PublicDashboardServiceImpl, db.ReplDB, *setting.Cfg) { +) (*PublicDashboardServiceImpl, db.DB, *setting.Cfg) { t.Helper() - db, cfg := db.InitTestReplDBWithCfg(t) + db, cfg := db.InitTestDBWithCfg(t) tagService := tagimpl.ProvideService(db) if annotationsRepo == nil { annotationsRepo = annotationsimpl.ProvideService(db, cfg, featuremgmt.WithFeatures(), tagService, tracing.InitializeTracerForTest(), nil) diff --git a/pkg/services/publicdashboards/service/query_test.go b/pkg/services/publicdashboards/service/query_test.go index e82d452e77a..7a356effc7b 100644 --- a/pkg/services/publicdashboards/service/query_test.go +++ b/pkg/services/publicdashboards/service/query_test.go @@ -10,9 +10,6 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" "github.com/grafana/grafana-plugin-sdk-go/data" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/db" @@ -28,6 +25,10 @@ import ( "github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/util" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" ) const ( @@ -681,7 +682,7 @@ func TestGetQueryDataResponse(t *testing.T) { fakeQueryService.On("QueryData", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&backend.QueryDataResponse{}, nil) service.QueryDataService = fakeQueryService - dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, service.cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotatest.New(false, nil)) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, service.cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotatest.New(false, nil)) require.NoError(t, err) publicDashboardQueryDTO := PublicDashboardQueryDTO{ @@ -1084,7 +1085,7 @@ func TestFindAnnotations(t *testing.T) { func TestGetMetricRequest(t *testing.T) { service, sqlStore, cfg := newPublicDashboardServiceImpl(t, nil, nil, nil) - dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotatest.New(false, nil)) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotatest.New(false, nil)) require.NoError(t, err) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]interface{}{}, nil) @@ -1166,7 +1167,7 @@ func TestBuildMetricRequest(t *testing.T) { fakeDashboardService := &dashboards.FakeDashboardService{} service, sqlStore, cfg := newPublicDashboardServiceImpl(t, nil, fakeDashboardService, nil) - dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotatest.New(false, nil)) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotatest.New(false, nil)) require.NoError(t, err) publicDashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]interface{}{}, nil) nonPublicDashboard := insertTestDashboard(t, dashboardStore, "testNonPublicDashie", 1, 0, "", true, []map[string]interface{}{}, nil) @@ -1319,7 +1320,7 @@ func TestBuildMetricRequest(t *testing.T) { } func TestBuildAnonymousUser(t *testing.T) { - sqlStore, cfg := db.InitTestReplDBWithCfg(t) + sqlStore, cfg := db.InitTestDBWithCfg(t) dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotatest.New(false, nil)) require.NoError(t, err) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]interface{}{}, nil) diff --git a/pkg/services/publicdashboards/service/service_test.go b/pkg/services/publicdashboards/service/service_test.go index 2970fbb9b87..fa28eed134c 100644 --- a/pkg/services/publicdashboards/service/service_test.go +++ b/pkg/services/publicdashboards/service/service_test.go @@ -586,7 +586,7 @@ func TestCreatePublicDashboard(t *testing.T) { service, sqlStore, cfg := newPublicDashboardServiceImpl(t, nil, fakeDashboardService, nil) quotaService := quotatest.New(false, nil) - dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]any{}, nil) fakeDashboardService.On("GetDashboard", mock.Anything, mock.Anything, mock.Anything).Return(dashboard, nil) @@ -666,7 +666,7 @@ func TestCreatePublicDashboard(t *testing.T) { fakeDashboardService := &dashboards.FakeDashboardService{} service, sqlStore, cfg := newPublicDashboardServiceImpl(t, nil, fakeDashboardService, nil) quotaService := quotatest.New(false, nil) - dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]any{}, nil) fakeDashboardService.On("GetDashboard", mock.Anything, mock.Anything, mock.Anything).Return(dashboard, nil) @@ -698,7 +698,7 @@ func TestCreatePublicDashboard(t *testing.T) { fakeDashboardService := &dashboards.FakeDashboardService{} service, sqlStore, cfg := newPublicDashboardServiceImpl(t, nil, fakeDashboardService, nil) quotaService := quotatest.New(false, nil) - dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]any{}, nil) fakeDashboardService.On("GetDashboard", mock.Anything, mock.Anything, mock.Anything).Return(dashboard, nil) @@ -725,7 +725,7 @@ func TestCreatePublicDashboard(t *testing.T) { fakeDashboardService := &dashboards.FakeDashboardService{} service, sqlStore, cfg := newPublicDashboardServiceImpl(t, nil, fakeDashboardService, nil) quotaService := quotatest.New(false, nil) - dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) templateVars := make([]map[string]any, 1) @@ -791,7 +791,7 @@ func TestCreatePublicDashboard(t *testing.T) { fakeDashboardService := &dashboards.FakeDashboardService{} service, sqlStore, cfg := newPublicDashboardServiceImpl(t, nil, fakeDashboardService, nil) quotaService := quotatest.New(false, nil) - dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]any{}, nil) fakeDashboardService.On("GetDashboard", mock.Anything, mock.Anything, mock.Anything).Return(dashboard, nil) @@ -857,7 +857,7 @@ func TestCreatePublicDashboard(t *testing.T) { fakeDashboardService := &dashboards.FakeDashboardService{} service, sqlStore, cfg := newPublicDashboardServiceImpl(t, nil, fakeDashboardService, nil) quotaService := quotatest.New(false, nil) - dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]interface{}{}, nil) fakeDashboardService.On("GetDashboard", mock.Anything, mock.Anything, mock.Anything).Return(dashboard, nil) @@ -909,7 +909,7 @@ func TestCreatePublicDashboard(t *testing.T) { fakeDashboardService := &dashboards.FakeDashboardService{} service, sqlStore, cfg := newPublicDashboardServiceImpl(t, publicdashboardStore, fakeDashboardService, nil) - dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotatest.New(false, nil)) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotatest.New(false, nil)) require.NoError(t, err) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]any{}, nil) fakeDashboardService.On("GetDashboard", mock.Anything, mock.Anything, mock.Anything).Return(dashboard, nil) @@ -935,7 +935,7 @@ func TestCreatePublicDashboard(t *testing.T) { service, sqlStore, cfg := newPublicDashboardServiceImpl(t, nil, fakeDashboardService, nil) quotaService := quotatest.New(false, nil) - dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]any{}, nil) fakeDashboardService.On("GetDashboard", mock.Anything, mock.Anything, mock.Anything).Return(dashboard, nil) @@ -973,7 +973,7 @@ func TestUpdatePublicDashboard(t *testing.T) { service, sqlStore, cfg := newPublicDashboardServiceImpl(t, nil, fakeDashboardService, nil) quotaService := quotatest.New(false, nil) - dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]any{}, nil) dashboard2 := insertTestDashboard(t, dashboardStore, "testDashie2", 1, 0, "", true, []map[string]any{}, nil) @@ -1156,7 +1156,7 @@ func TestUpdatePublicDashboard(t *testing.T) { service, sqlStore, cfg := newPublicDashboardServiceImpl(t, nil, fakeDashboardService, nil) quotaService := quotatest.New(false, nil) - dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore.DB()), quotaService) + dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]any{}, nil) fakeDashboardService.On("GetDashboard", mock.Anything, mock.Anything, mock.Anything).Return(dashboard, nil) diff --git a/pkg/services/quota/quotaimpl/quota.go b/pkg/services/quota/quotaimpl/quota.go index e8867ad38e8..34ba998317f 100644 --- a/pkg/services/quota/quotaimpl/quota.go +++ b/pkg/services/quota/quotaimpl/quota.go @@ -58,7 +58,7 @@ type service struct { targetToSrv *quota.TargetToSrv } -func ProvideService(db db.ReplDB, cfg *setting.Cfg) quota.Service { +func ProvideService(db db.DB, cfg *setting.Cfg) quota.Service { logger := log.New("quota_service") s := service{ store: &sqlStore{db: db, logger: logger}, diff --git a/pkg/services/quota/quotaimpl/quota_test.go b/pkg/services/quota/quotaimpl/quota_test.go index 4c334396003..66763397395 100644 --- a/pkg/services/quota/quotaimpl/quota_test.go +++ b/pkg/services/quota/quotaimpl/quota_test.go @@ -69,7 +69,7 @@ func TestIntegrationQuotaCommandsAndQueries(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - sqlStore, cfg := db.InitTestReplDBWithCfg(t) + sqlStore, cfg := db.InitTestDBWithCfg(t) cfg.Quota = setting.QuotaSettings{ Enabled: true, @@ -479,14 +479,13 @@ func getQuotaBySrvTargetScope(t *testing.T, quotaService quota.Service, srv quot return quota.QuotaDTO{}, err } -func setupEnv(t *testing.T, replStore db.ReplDB, cfg *setting.Cfg, b bus.Bus, quotaService quota.Service) { - sqlStore := replStore.DB() +func setupEnv(t *testing.T, sqlStore db.DB, cfg *setting.Cfg, b bus.Bus, quotaService quota.Service) { tracer := tracing.InitializeTracerForTest() _, err := apikeyimpl.ProvideService(sqlStore, cfg, quotaService) require.NoError(t, err) _, err = authimpl.ProvideUserAuthTokenService(sqlStore, nil, quotaService, cfg) require.NoError(t, err) - _, err = dashboardStore.ProvideDashboardStore(replStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) + _, err = dashboardStore.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) diff --git a/pkg/services/quota/quotaimpl/store.go b/pkg/services/quota/quotaimpl/store.go index 743e4f20275..78bc38fe4d9 100644 --- a/pkg/services/quota/quotaimpl/store.go +++ b/pkg/services/quota/quotaimpl/store.go @@ -16,12 +16,12 @@ type store interface { } type sqlStore struct { - db db.ReplDB + db db.DB logger log.Logger } func (ss *sqlStore) DeleteByUser(ctx quota.Context, userID int64) error { - return ss.db.DB().WithDbSession(ctx, func(sess *db.Session) error { + return ss.db.WithDbSession(ctx, func(sess *db.Session) error { var rawSQL = "DELETE FROM quota WHERE user_id = ?" _, err := sess.Exec(rawSQL, userID) return err @@ -54,7 +54,7 @@ func (ss *sqlStore) Get(ctx quota.Context, scopeParams *quota.ScopeParameters) ( } func (ss *sqlStore) Update(ctx quota.Context, cmd *quota.UpdateQuotaCmd) error { - return ss.db.DB().WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { + return ss.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { // Check if quota is already defined in the DB quota := quota.Quota{ Target: cmd.Target, @@ -87,7 +87,7 @@ func (ss *sqlStore) Update(ctx quota.Context, cmd *quota.UpdateQuotaCmd) error { func (ss *sqlStore) getUserScopeQuota(ctx quota.Context, userID int64) (*quota.Map, error) { r := quota.Map{} - err := ss.db.ReadReplica().WithDbSession(ctx, func(sess *sqlstore.DBSession) error { + err := ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { quotas := make([]*quota.Quota, 0) if err := sess.Table("quota").Where("user_id=? AND org_id=0", userID).Find("as); err != nil { return err @@ -111,7 +111,7 @@ func (ss *sqlStore) getUserScopeQuota(ctx quota.Context, userID int64) (*quota.M func (ss *sqlStore) getOrgScopeQuota(ctx quota.Context, OrgID int64) (*quota.Map, error) { r := quota.Map{} - err := ss.db.ReadReplica().WithDbSession(ctx, func(sess *sqlstore.DBSession) error { + err := ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { quotas := make([]*quota.Quota, 0) if err := sess.Table("quota").Where("user_id=0 AND org_id=?", OrgID).Find("as); err != nil { return err diff --git a/pkg/services/quota/quotaimpl/store_test.go b/pkg/services/quota/quotaimpl/store_test.go index 0128f86ad1d..2e8211871d1 100644 --- a/pkg/services/quota/quotaimpl/store_test.go +++ b/pkg/services/quota/quotaimpl/store_test.go @@ -20,7 +20,7 @@ func TestIntegrationQuotaDataAccess(t *testing.T) { t.Skip("skipping integration test") } - ss := db.InitTestReplDB(t) + ss := db.InitTestDB(t) quotaStore := sqlStore{ db: ss, } diff --git a/pkg/services/searchV2/index_test.go b/pkg/services/searchV2/index_test.go index bc1d4b5d07b..e6a569fb57c 100644 --- a/pkg/services/searchV2/index_test.go +++ b/pkg/services/searchV2/index_test.go @@ -773,8 +773,7 @@ func TestIntegrationSoftDeletion(t *testing.T) { // Set up search v2. folderCount := 1 dashboardsPerFolder := 1 - replStore, cfg := db.InitTestReplDBWithCfg(t) - sqlStore := replStore.DB() + sqlStore, cfg := db.InitTestDBWithCfg(t) searchService, testUser, err := setupIntegrationEnv(t, folderCount, dashboardsPerFolder, sqlStore) require.NoError(t, err) @@ -796,7 +795,7 @@ func TestIntegrationSoftDeletion(t *testing.T) { featuremgmt.FlagDashboardRestore, featuremgmt.FlagMysqlParseTime, ) - dashboardStore, err := database.ProvideDashboardStore(replStore, cfg, featureToggles, tagimpl.ProvideService(sqlStore), quotaService) + dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featureToggles, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) // Soft delete "dashboard2". diff --git a/pkg/services/serviceaccounts/tests/common.go b/pkg/services/serviceaccounts/tests/common.go index 5ef35d18c59..66d15e35b9d 100644 --- a/pkg/services/serviceaccounts/tests/common.go +++ b/pkg/services/serviceaccounts/tests/common.go @@ -36,17 +36,17 @@ type TestApiKey struct { ServiceAccountID *int64 } -func SetupUserServiceAccount(t *testing.T, store db.DB, cfg *setting.Cfg, testUser TestUser) *user.User { +func SetupUserServiceAccount(t *testing.T, db db.DB, cfg *setting.Cfg, testUser TestUser) *user.User { role := string(org.RoleViewer) if testUser.Role != "" { role = testUser.Role } - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(store), cfg) - orgService, err := orgimpl.ProvideService(store, cfg, quotaService) + quotaService := quotaimpl.ProvideService(db, cfg) + orgService, err := orgimpl.ProvideService(db, cfg, quotaService) require.NoError(t, err) usrSvc, err := userimpl.ProvideService( - store, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), + db, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), quotaService, supportbundlestest.NewFakeBundleService(), ) require.NoError(t, err) @@ -112,7 +112,7 @@ func SetupApiKey(t *testing.T, store db.DB, cfg *setting.Cfg, testKey TestApiKey func SetupUsersServiceAccounts(t *testing.T, sqlStore db.DB, cfg *setting.Cfg, testUsers []TestUser) (orgID int64) { role := string(org.RoleNone) - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(sqlStore), cfg) + quotaService := quotaimpl.ProvideService(sqlStore, cfg) orgService, err := orgimpl.ProvideService(sqlStore, cfg, quotaService) require.NoError(t, err) usrSvc, err := userimpl.ProvideService( diff --git a/pkg/services/sqlstore/database_config.go b/pkg/services/sqlstore/database_config.go index e469455670f..171ff4972b9 100644 --- a/pkg/services/sqlstore/database_config.go +++ b/pkg/services/sqlstore/database_config.go @@ -10,7 +10,6 @@ import ( "strings" "github.com/go-sql-driver/mysql" - "gopkg.in/ini.v1" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/sqlstore/migrator" @@ -66,15 +65,9 @@ func NewDatabaseConfig(cfg *setting.Cfg, features featuremgmt.FeatureToggles) (* return dbCfg, nil } -// readConfigSection reads the database configuration from the given block of -// the configuration file. This method allows us to add a "database_replica" -// section to the configuration file while using the same cfg struct. -func (dbCfg *DatabaseConfig) readConfigSection(cfg *setting.Cfg, section string) error { - sec := cfg.Raw.Section(section) - return dbCfg.parseConfigIni(sec) -} +func (dbCfg *DatabaseConfig) readConfig(cfg *setting.Cfg) error { + sec := cfg.Raw.Section("database") -func (dbCfg *DatabaseConfig) parseConfigIni(sec *ini.Section) error { cfgURL := sec.Key("url").String() if len(cfgURL) != 0 { dbURL, err := url.Parse(cfgURL) @@ -108,6 +101,7 @@ func (dbCfg *DatabaseConfig) parseConfigIni(sec *ini.Section) error { dbCfg.MaxOpenConn = sec.Key("max_open_conn").MustInt(0) dbCfg.MaxIdleConn = sec.Key("max_idle_conn").MustInt(2) dbCfg.ConnMaxLifetime = sec.Key("conn_max_lifetime").MustInt(14400) + dbCfg.SslMode = sec.Key("ssl_mode").String() dbCfg.SSLSNI = sec.Key("ssl_sni").String() dbCfg.CaCertPath = sec.Key("ca_cert_path").String() @@ -116,20 +110,19 @@ func (dbCfg *DatabaseConfig) parseConfigIni(sec *ini.Section) error { dbCfg.ServerCertName = sec.Key("server_cert_name").String() dbCfg.Path = sec.Key("path").MustString("data/grafana.db") dbCfg.IsolationLevel = sec.Key("isolation_level").String() + dbCfg.CacheMode = sec.Key("cache_mode").MustString("private") dbCfg.WALEnabled = sec.Key("wal").MustBool(false) dbCfg.SkipMigrations = sec.Key("skip_migrations").MustBool() dbCfg.MigrationLock = sec.Key("migration_locking").MustBool(true) dbCfg.MigrationLockAttemptTimeout = sec.Key("locking_attempt_timeout_sec").MustInt() + dbCfg.QueryRetries = sec.Key("query_retries").MustInt() dbCfg.TransactionRetries = sec.Key("transaction_retries").MustInt(5) - dbCfg.LogQueries = sec.Key("log_queries").MustBool(false) - return nil -} -// readConfig is a wrapper around readConfigSection that read the "database" configuration block. -func (dbCfg *DatabaseConfig) readConfig(cfg *setting.Cfg) error { - return dbCfg.readConfigSection(cfg, "database") + dbCfg.LogQueries = sec.Key("log_queries").MustBool(false) + + return nil } func (dbCfg *DatabaseConfig) buildConnectionString(cfg *setting.Cfg, features featuremgmt.FeatureToggles) error { @@ -235,50 +228,3 @@ func buildExtraConnectionString(sep rune, urlQueryParams map[string][]string) st } return sb.String() } - -func validateReplicaConfigs(primary *DatabaseConfig, cfgs []DatabaseConfig) error { - if cfgs == nil { - return errors.New("cfg cannot be nil") - } - - // Return multiple errors so we can fix them all at once! - var result error - - // Check for duplicate connection strings - seen := make(map[string]struct{}) - seen[primary.ConnectionString] = struct{}{} - for _, cfg := range cfgs { - if _, ok := seen[cfg.ConnectionString]; ok { - result = errors.Join(result, errors.New("duplicate connection string")) - } else { - seen[cfg.ConnectionString] = struct{}{} - } - } - - // Verify that every database is the same type and version, and that it matches the primary database. - // The database Yype may include a "withHooks" suffix, which is used to differentiate drivers for instrumentation and ignored for the purpose of this check. - for _, cfg := range cfgs { - if databaseDriverFromName(cfg.Type) != databaseDriverFromName(primary.Type) { - result = errors.Join(result, fmt.Errorf("the replicas must have the same database type as the primary database (%s != %s)", primary.Type, cfg.Type)) - break // Only need to report this once - } - } - - return result -} - -// databaseDriverFromName strips any suffixes from the driver type that are not relevant to the database driver. -// This is used to remove the "WithHooks" or "ReplWithHooks" suffixes which are used to differentiate drivers for instrumentation. -func databaseDriverFromName(driverTy string) string { - if strings.HasPrefix(driverTy, migrator.MySQL) { - return migrator.MySQL - } - if strings.HasPrefix(driverTy, migrator.Postgres) { - return migrator.Postgres - } - if strings.HasPrefix(driverTy, migrator.SQLite) { - return migrator.SQLite - } - // default - return driverTy -} diff --git a/pkg/services/sqlstore/database_config_test.go b/pkg/services/sqlstore/database_config_test.go index 5dd882f85b6..cd13fc3b8fa 100644 --- a/pkg/services/sqlstore/database_config_test.go +++ b/pkg/services/sqlstore/database_config_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gopkg.in/ini.v1" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/sqlstore/migrator" @@ -222,93 +221,3 @@ func TestBuildConnectionStringPostgres(t *testing.T) { }) } } - -func TestValidateReplicaConfigs(t *testing.T) { - t.Run("valid config", func(t *testing.T) { - inicfg, err := ini.Load([]byte(testReplCfg)) - require.NoError(t, err) - cfg, err := setting.NewCfgFromINIFile(inicfg) - require.NoError(t, err) - - dbCfgs, err := NewRODatabaseConfigs(cfg, nil) - require.NoError(t, err) - - err = validateReplicaConfigs(&DatabaseConfig{Type: "mysql"}, dbCfgs) - require.NoError(t, err) - }) - - t.Run("valid but awkward config", func(t *testing.T) { - inicfg, err := ini.Load([]byte(testReplCfg)) - require.NoError(t, err) - cfg, err := setting.NewCfgFromINIFile(inicfg) - require.NoError(t, err) - - dbCfgs, err := NewRODatabaseConfigs(cfg, nil) - require.NoError(t, err) - - // The primary is mysql, but the replicas are mysqlWithHooks. This can - // occur when some but not all the replicas (or primary) have - // instrument_queries enabled - err = validateReplicaConfigs(&DatabaseConfig{Type: "mysqlWithHooks"}, dbCfgs) - require.NoError(t, err) - }) - - t.Run("invalid config: primary database type mismatch", func(t *testing.T) { - // valid repl config, the issue is that the primary has a different type - inicfg, err := ini.Load([]byte(testReplCfg)) - require.NoError(t, err) - cfg, err := setting.NewCfgFromINIFile(inicfg) - require.NoError(t, err) - - dbCfgs, err := NewRODatabaseConfigs(cfg, nil) - require.NoError(t, err) - - err = validateReplicaConfigs(&DatabaseConfig{Type: "postgres"}, dbCfgs) - require.Error(t, err) - - if uw, ok := err.(interface{ Unwrap() []error }); ok { - errs := uw.Unwrap() - require.Equal(t, 1, len(errs)) - } - }) - - t.Run("invalid repl config", func(t *testing.T) { - // Type mismatch + duplicate hosts - inicfg, err := ini.Load([]byte(invalidReplCfg)) - require.NoError(t, err) - cfg, err := setting.NewCfgFromINIFile(inicfg) - require.NoError(t, err) - - dbCfgs, err := NewRODatabaseConfigs(cfg, nil) - require.NoError(t, err) - - err = validateReplicaConfigs(&DatabaseConfig{Type: "mysql"}, dbCfgs) - require.Error(t, err) - - if uw, ok := err.(interface{ Unwrap() []error }); ok { - errs := uw.Unwrap() - require.Equal(t, 2, len(errs)) - } - }) -} - -// This cfg has a duplicate host for repls 0 and 1, and a type mismatch in repl 2 -var invalidReplCfg = ` -[database_replicas] -type = mysql -name = grafana -user = grafana -password = password -host = 127.0.0.1:3306 -[database_replica.one] -name = grafana -user = grafana -password = password -type = mysql -host = 127.0.0.1:3306 -[database_replica.two] -name = grafana -user = grafana -password = password -type = postgres -host = 127.0.0.1:3308` diff --git a/pkg/services/sqlstore/database_wrapper.go b/pkg/services/sqlstore/database_wrapper.go index b6358e73002..d173f48158a 100644 --- a/pkg/services/sqlstore/database_wrapper.go +++ b/pkg/services/sqlstore/database_wrapper.go @@ -58,27 +58,6 @@ func WrapDatabaseDriverWithHooks(dbType string, tracer tracing.Tracer) string { return driverWithHooks } -// WrapDatabaseDriverWithHooks creates a fake database driver that -// executes pre and post functions which we use to gather metrics about -// database queries. It also registers the metrics. -func WrapDatabaseReplDriverWithHooks(dbType string, index uint, tracer tracing.Tracer) string { - drivers := map[string]driver.Driver{ - migrator.SQLite: &sqlite3.SQLiteDriver{}, - migrator.MySQL: &mysql.MySQLDriver{}, - migrator.Postgres: &pq.Driver{}, - } - - d, exist := drivers[dbType] - if !exist { - return dbType - } - - driverWithHooks := dbType + fmt.Sprintf("ReplicaWithHooks%d", index) - sql.Register(driverWithHooks, sqlhooks.Wrap(d, &databaseQueryWrapper{log: log.New("sqlstore.metrics"), tracer: tracer})) - core.RegisterDriver(driverWithHooks, &databaseQueryWrapperDriver{dbType: dbType}) - return driverWithHooks -} - // databaseQueryWrapper satisfies the sqlhook.databaseQueryWrapper interface // which allow us to wrap all SQL queries with a `Before` & `After` hook. type databaseQueryWrapper struct { diff --git a/pkg/services/sqlstore/migrator/dialect.go b/pkg/services/sqlstore/migrator/dialect.go index ff9ec8ef8f3..5aae742b6ca 100644 --- a/pkg/services/sqlstore/migrator/dialect.go +++ b/pkg/services/sqlstore/migrator/dialect.go @@ -6,10 +6,9 @@ import ( "strconv" "strings" + "github.com/grafana/grafana/pkg/services/sqlstore/session" "golang.org/x/exp/slices" "xorm.io/xorm" - - "github.com/grafana/grafana/pkg/services/sqlstore/session" ) var ( @@ -107,14 +106,12 @@ type LockCfg struct { type dialectFunc func() Dialect var supportedDialects = map[string]dialectFunc{ - MySQL: NewMysqlDialect, - SQLite: NewSQLite3Dialect, - Postgres: NewPostgresDialect, - MySQL + "WithHooks": NewMysqlDialect, - MySQL + "ReplicaWithHooks": NewMysqlDialect, - SQLite + "WithHooks": NewSQLite3Dialect, - Postgres + "WithHooks": NewPostgresDialect, - Postgres + "ReplicaWithHooks": NewPostgresDialect, + MySQL: NewMysqlDialect, + SQLite: NewSQLite3Dialect, + Postgres: NewPostgresDialect, + MySQL + "WithHooks": NewMysqlDialect, + SQLite + "WithHooks": NewSQLite3Dialect, + Postgres + "WithHooks": NewPostgresDialect, } func NewDialect(driverName string) Dialect { diff --git a/pkg/services/sqlstore/permissions/dashboard_test.go b/pkg/services/sqlstore/permissions/dashboard_test.go index 1acf17fce41..4c184e56e17 100644 --- a/pkg/services/sqlstore/permissions/dashboard_test.go +++ b/pkg/services/sqlstore/permissions/dashboard_test.go @@ -816,7 +816,7 @@ func setupTest(t *testing.T, numFolders, numDashboards int, permissions []access func setupNestedTest(t *testing.T, usr *user.SignedInUser, perms []accesscontrol.Permission, orgID int64, features featuremgmt.FeatureToggles) db.DB { t.Helper() - db, cfg := db.InitTestReplDBWithCfg(t) + db, cfg := db.InitTestDBWithCfg(t) // dashboard store commands that should be called. dashStore, err := database.ProvideDashboardStore(db, cfg, features, tagimpl.ProvideService(db), quotatest.New(false, nil)) diff --git a/pkg/services/sqlstore/permissions/dashboards_bench_test.go b/pkg/services/sqlstore/permissions/dashboards_bench_test.go index dfb2fe43b81..4dc62cadd3a 100644 --- a/pkg/services/sqlstore/permissions/dashboards_bench_test.go +++ b/pkg/services/sqlstore/permissions/dashboards_bench_test.go @@ -74,7 +74,7 @@ func setupBenchMark(b *testing.B, usr user.SignedInUser, features featuremgmt.Fe nestingLevel = folder.MaxNestedFolderDepth } - store, cfg := db.InitTestReplDBWithCfg(b) + store, cfg := db.InitTestDBWithCfg(b) quotaService := quotatest.New(false, nil) diff --git a/pkg/services/sqlstore/replstore.go b/pkg/services/sqlstore/replstore.go deleted file mode 100644 index 68854acde0a..00000000000 --- a/pkg/services/sqlstore/replstore.go +++ /dev/null @@ -1,277 +0,0 @@ -package sqlstore - -import ( - "errors" - "fmt" - "regexp" - "sync/atomic" - "time" - - "github.com/dlmiddlecote/sqlstats" - "github.com/prometheus/client_golang/prometheus" - "xorm.io/xorm" - - "github.com/grafana/grafana/pkg/bus" - "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/infra/tracing" - "github.com/grafana/grafana/pkg/registry" - "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/services/sqlstore/migrations" - "github.com/grafana/grafana/pkg/services/sqlstore/migrator" - "github.com/grafana/grafana/pkg/services/sqlstore/sqlutil" - "github.com/grafana/grafana/pkg/setting" -) - -// ReplStore is a wrapper around a main SQLStore and a read-only SQLStore. The -// main SQLStore is anonymous, so the ReplStore may be used directly as a -// SQLStore. -type ReplStore struct { - *SQLStore - repls []*SQLStore - - // next is the index of the next read-only SQLStore in the chain. - next uint64 -} - -// DB returns the main SQLStore. -func (rs *ReplStore) DB() *SQLStore { - return rs.SQLStore -} - -// ReadReplica returns the read-only SQLStore. If no read replica is configured, -// it returns the main SQLStore. -func (rs *ReplStore) ReadReplica() *SQLStore { - if len(rs.repls) == 0 { - rs.log.Debug("ReadReplica not configured, using main SQLStore") - return rs.SQLStore - } - return rs.nextRepl() -} - -// nextRepl() returns the next read-only SQLStore in the chain. If no read replica is configured, the Primary is returned. -func (rs *ReplStore) nextRepl() *SQLStore { - // start by grabbing the replica at the current index - selected := rs.repls[(int(rs.next))%len(rs.repls)] - - // then increment the index for the next call - atomic.AddUint64(&rs.next, 1) - - return selected -} - -// ProvideServiceWithReadReplica creates a new *SQLStore connection intended for -// use as a ReadReplica of the main SQLStore. The primary SQLStore must already -// be initialized. -func ProvideServiceWithReadReplica(primary *SQLStore, cfg *setting.Cfg, - features featuremgmt.FeatureToggles, migrations registry.DatabaseMigrator, - bus bus.Bus, tracer tracing.Tracer) (*ReplStore, error) { - // start with the initialized SQLStore - replStore := &ReplStore{primary, nil, 0} - - // FeatureToggle fallback: If the FlagDatabaseReadReplica feature flag is not enabled, return a single SQLStore. - if !features.IsEnabledGlobally(featuremgmt.FlagDatabaseReadReplica) { - primary.log.Debug("ReadReplica feature flag not enabled, using main SQLStore") - return replStore, nil - } - - // This change will make xorm use an empty default schema for postgres and - // by that mimic the functionality of how it was functioning before - // xorm's changes above. - xorm.DefaultPostgresSchema = "" - - // Parsing the configuration to get the number of repls - replCfgs, err := NewRODatabaseConfigs(cfg, features) - if err != nil { - return nil, err - } - - if err := validateReplicaConfigs(primary.dbCfg, replCfgs); err != nil { - return nil, fmt.Errorf("failed to validate replica configurations: %w", err) - } - - if len(replCfgs) > 0 { - replStore.repls = make([]*SQLStore, len(replCfgs)) - } - - for i, replCfg := range replCfgs { - // If the database_instrument_queries feature is enabled, wrap the driver with hooks. - if cfg.DatabaseInstrumentQueries { - replCfg.Type = WrapDatabaseReplDriverWithHooks(replCfg.Type, uint(i), tracer) - } - - s, err := newReadOnlySQLStore(cfg, &replCfg, features, bus, tracer) - if err != nil { - return nil, err - } - - // initialize and register metrics wrapper around the *sql.DB - db := s.engine.DB().DB - - // register the go_sql_stats_connections_* metrics - if err := prometheus.Register(sqlstats.NewStatsCollector("grafana_repl", db)); err != nil { - s.log.Warn("Failed to register sqlstore stats collector", "error", err) - } - replStore.repls[i] = s - } - return replStore, nil -} - -// newReadOnlySQLStore creates a new *SQLStore intended for use with a -// fully-populated read replica of the main Grafana Database. It provides no -// write capabilities and does not run migrations, but other tracing and logging -// features are enabled. -func newReadOnlySQLStore(cfg *setting.Cfg, dbCfg *DatabaseConfig, features featuremgmt.FeatureToggles, bus bus.Bus, tracer tracing.Tracer) (*SQLStore, error) { - s := &SQLStore{ - log: log.New("replstore"), - bus: bus, - tracer: tracer, - features: features, - dbCfg: dbCfg, - cfg: cfg, - } - - err := s.initReadOnlyEngine(s.engine) - if err != nil { - return nil, err - } - - // When there are multiple read replicas, we append an index to the driver name (ex: mysqlWithHooks11). - // Remove the index from the end of the driver name to get the original driver name that xorm and other libraries recognize. - driverName := digitsRegexp.ReplaceAllString(s.engine.DriverName(), "") - - s.dialect = migrator.NewDialect(driverName) - return s, nil -} - -// digitsRegexp is used to remove the index from the end of the driver name. -var digitsRegexp = regexp.MustCompile("[0-9]+") - -// initReadOnlyEngine initializes ss.engine for read-only operations. The database must be a fully-populated read replica. -func (ss *SQLStore) initReadOnlyEngine(engine *xorm.Engine) error { - if ss.engine != nil { - ss.log.Debug("Already connected to database replica") - return nil - } - - if engine == nil { - var err error - engine, err = xorm.NewEngine(ss.dbCfg.Type, ss.dbCfg.ConnectionString) - if err != nil { - ss.log.Error("failed to connect to database replica", "error", err) - return err - } - // Only for MySQL or MariaDB, verify we can connect with the current connection string's system var for transaction isolation. - // If not, create a new engine with a compatible connection string. - if ss.dbCfg.Type == migrator.MySQL { - engine, err = ss.ensureTransactionIsolationCompatibility(engine, ss.dbCfg.ConnectionString) - if err != nil { - return err - } - } - } - - engine.SetMaxOpenConns(ss.dbCfg.MaxOpenConn) - engine.SetMaxIdleConns(ss.dbCfg.MaxIdleConn) - engine.SetConnMaxLifetime(time.Second * time.Duration(ss.dbCfg.ConnMaxLifetime)) - - // configure sql logging - debugSQL := ss.cfg.Raw.Section("database_replica").Key("log_queries").MustBool(false) - if !debugSQL { - engine.SetLogger(&xorm.DiscardLogger{}) - } else { - // add stack to database calls to be able to see what repository initiated queries. Top 7 items from the stack as they are likely in the xorm library. - engine.SetLogger(NewXormLogger(log.LvlInfo, log.WithSuffix(log.New("replsstore.xorm"), log.CallerContextKey, log.StackCaller(log.DefaultCallerDepth)))) - engine.ShowSQL(true) - engine.ShowExecTime(true) - } - - ss.engine = engine - return nil -} - -// NewRODatabaseConfig creates a new read-only database configuration. -func NewRODatabaseConfigs(cfg *setting.Cfg, features featuremgmt.FeatureToggles) ([]DatabaseConfig, error) { - if cfg == nil { - return nil, errors.New("cfg cannot be nil") - } - - // If one replica is configured in the database_replicas section, use it as the default - defaultReplCfg := DatabaseConfig{} - if err := defaultReplCfg.readConfigSection(cfg, "database_replicas"); err != nil { - return nil, err - } - err := defaultReplCfg.buildConnectionString(cfg, features) - if err != nil { - return nil, err - } - ret := []DatabaseConfig{defaultReplCfg} - - // Check for individual replicas in the database_replica section (e.g. database_replica.one, database_replica.cheetara) - repls := cfg.Raw.Section("database_replica") - if len(repls.ChildSections()) > 0 { - for _, sec := range repls.ChildSections() { - replCfg := DatabaseConfig{} - if err := replCfg.parseConfigIni(sec); err != nil { - return nil, err - } - if err := replCfg.buildConnectionString(cfg, features); err != nil { - return nil, err - } - ret = append(ret, replCfg) - } - } - - return ret, nil -} - -// ProvideServiceWithReadReplicaForTests wraps the SQLStore in a ReplStore, with the main sqlstore as both the primary and read replica. -// TODO: eventually this should be replaced with a more robust test setup which in -func ProvideServiceWithReadReplicaForTests(testDB *SQLStore, t sqlutil.ITestDB, cfg *setting.Cfg, features featuremgmt.FeatureToggles, migrations registry.DatabaseMigrator) (*ReplStore, error) { - return newReplStore(testDB, testDB), nil -} - -// InitTestReplDB initializes a test DB and returns it wrapped in a ReplStore with the main SQLStore as both the primary and read replica. -func InitTestReplDB(t sqlutil.ITestDB, opts ...InitTestDBOpt) (*ReplStore, *setting.Cfg) { - t.Helper() - features := getFeaturesForTesting(opts...) - cfg := getCfgForTesting(opts...) - ss, err := initTestDB(t, cfg, features, migrations.ProvideOSSMigrations(features), opts...) - if err != nil { - t.Fatalf("failed to initialize sql repl store: %s", err) - } - return newReplStore(ss, ss), cfg -} - -// InitTestReplDBWithMigration initializes the test DB given custom migrations. -func InitTestReplDBWithMigration(t sqlutil.ITestDB, migration registry.DatabaseMigrator, opts ...InitTestDBOpt) *ReplStore { - t.Helper() - features := getFeaturesForTesting(opts...) - cfg := getCfgForTesting(opts...) - ss, err := initTestDB(t, cfg, features, migration, opts...) - if err != nil { - t.Fatalf("failed to initialize sql store: %s", err) - } - return newReplStore(ss, ss) -} - -// newReplStore is a wrapper function that returns a ReplStore with the given primary and read replicas. -func newReplStore(primary *SQLStore, readReplicas ...*SQLStore) *ReplStore { - ret := &ReplStore{ - SQLStore: primary, - repls: make([]*SQLStore, len(readReplicas)), - next: 0, - } - ret.repls = readReplicas - return ret -} - -// FakeReplStoreFromStore returns a ReplStore with the given primary -// SQLStore and no read replicas. This is a bare-minimum wrapper for testing, -// and should be removed when all services are using ReplStore in favor of -// InitTestReplDB. -func FakeReplStoreFromStore(primary *SQLStore) *ReplStore { - return &ReplStore{ - SQLStore: primary, - next: 0, - } -} diff --git a/pkg/services/sqlstore/replstore_test.go b/pkg/services/sqlstore/replstore_test.go deleted file mode 100644 index 6cb475b3b06..00000000000 --- a/pkg/services/sqlstore/replstore_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package sqlstore - -import ( - "fmt" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/stretchr/testify/require" - "gopkg.in/ini.v1" - - "github.com/grafana/grafana/pkg/setting" -) - -func TestReplStore_ReadReplica(t *testing.T) { - // Using the connection strings to differentiate between the replicas - replStore, _ := InitTestReplDB(t) - replStore.repls[0].dbCfg.ConnectionString = "repl0" - - repl1 := &SQLStore{dbCfg: &DatabaseConfig{ConnectionString: "repl1"}} - repl2 := &SQLStore{dbCfg: &DatabaseConfig{ConnectionString: "repl2"}} - replStore.repls = append(replStore.repls, repl1, repl2) - - got := make([]string, 5) - for i := 0; i < 5; i++ { - got[i] = replStore.ReadReplica().dbCfg.ConnectionString - } - - want := []string{"repl0", "repl1", "repl2", "repl0", "repl1"} - if cmp.Equal(got, want) == false { - t.Fatal("wrong result. Got:", got, "Want:", want) - } -} - -func TestNewRODatabaseConfig(t *testing.T) { - t.Run("valid config", func(t *testing.T) { - inicfg, err := ini.Load([]byte(testReplCfg)) - require.NoError(t, err) - cfg, err := setting.NewCfgFromINIFile(inicfg) - require.NoError(t, err) - - dbCfgs, err := NewRODatabaseConfigs(cfg, nil) - require.NoError(t, err) - require.Len(t, dbCfgs, 3) - - var connStr = func(port int) string { - return fmt.Sprintf("grafana:password@tcp(127.0.0.1:%d)/grafana?collation=utf8mb4_unicode_ci&allowNativePasswords=true&clientFoundRows=true", port) - } - for i, c := range dbCfgs { - if !cmp.Equal(c.ConnectionString, connStr(i+3306)) { - t.Errorf("wrong result for connection string %d.\nGot: %s,\nWant: %s", i, c.ConnectionString, connStr(i+3306)) - } - } - }) -} - -var testReplCfg = ` -[database_replicas] -type = mysql -name = grafana -user = grafana -password = password -host = 127.0.0.1:3306 -[database_replica.one] -host = 127.0.0.1:3307 -type = mysql -name = grafana -user = grafana -password = password -[database_replica.two] -host = 127.0.0.1:3308 -type = mysql -name = grafana -user = grafana -password = password` diff --git a/pkg/services/stats/statsimpl/stats.go b/pkg/services/stats/statsimpl/stats.go index 7f580471212..e2139c80b57 100644 --- a/pkg/services/stats/statsimpl/stats.go +++ b/pkg/services/stats/statsimpl/stats.go @@ -9,7 +9,6 @@ import ( "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/services/libraryelements/model" "github.com/grafana/grafana/pkg/services/org" - "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore/migrator" "github.com/grafana/grafana/pkg/services/stats" "github.com/grafana/grafana/pkg/setting" @@ -18,12 +17,12 @@ import ( const activeUserTimeLimit = time.Hour * 24 * 30 const dailyActiveUserTimeLimit = time.Hour * 24 -func ProvideService(cfg *setting.Cfg, db *sqlstore.ReplStore) stats.Service { +func ProvideService(cfg *setting.Cfg, db db.DB) stats.Service { return &sqlStatsService{cfg: cfg, db: db} } type sqlStatsService struct { - db *sqlstore.ReplStore + db db.DB cfg *setting.Cfg } @@ -63,8 +62,8 @@ func notServiceAccount(dialect migrator.Dialect) string { } func (ss *sqlStatsService) GetSystemStats(ctx context.Context, query *stats.GetSystemStatsQuery) (result *stats.SystemStats, err error) { - dialect := ss.db.ReadReplica().GetDialect() - err = ss.db.ReadReplica().WithDbSession(ctx, func(dbSession *db.Session) error { + dialect := ss.db.GetDialect() + err = ss.db.WithDbSession(ctx, func(dbSession *db.Session) error { sb := &db.SQLBuilder{} sb.Write("SELECT ") sb.Write(`(SELECT COUNT(*) FROM ` + dialect.Quote("user") + ` WHERE ` + notServiceAccount(dialect) + `) AS users,`) @@ -149,8 +148,8 @@ func (ss *sqlStatsService) roleCounterSQL(ctx context.Context) string { } func (ss *sqlStatsService) GetAdminStats(ctx context.Context, query *stats.GetAdminStatsQuery) (result *stats.AdminStats, err error) { - err = ss.db.ReadReplica().WithDbSession(ctx, func(dbSession *db.Session) error { - dialect := ss.db.ReadReplica().GetDialect() + err = ss.db.WithDbSession(ctx, func(dbSession *db.Session) error { + dialect := ss.db.GetDialect() now := time.Now() activeEndDate := now.Add(-activeUserTimeLimit) dailyActiveEndDate := now.Add(-dailyActiveUserTimeLimit) diff --git a/pkg/services/stats/statsimpl/stats_test.go b/pkg/services/stats/statsimpl/stats_test.go index cce64977c32..e07c059bf9d 100644 --- a/pkg/services/stats/statsimpl/stats_test.go +++ b/pkg/services/stats/statsimpl/stats_test.go @@ -32,9 +32,9 @@ func TestIntegrationStatsDataAccess(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - store, cfg := db.InitTestReplDBWithCfg(t) - statsService := &sqlStatsService{db: store} - populateDB(t, store, cfg) + db, cfg := db.InitTestDBWithCfg(t) + statsService := &sqlStatsService{db: db} + populateDB(t, db, cfg) t.Run("Get system stats should not results in error", func(t *testing.T) { query := stats.GetSystemStatsQuery{} @@ -49,7 +49,7 @@ func TestIntegrationStatsDataAccess(t *testing.T) { assert.Equal(t, int64(0), result.APIKeys) assert.Equal(t, int64(2), result.Correlations) assert.NotNil(t, result.DatabaseCreatedTime) - assert.Equal(t, store.GetDialect().DriverName(), result.DatabaseDriver) + assert.Equal(t, db.GetDialect().DriverName(), result.DatabaseDriver) }) t.Run("Get system user count stats should not results in error", func(t *testing.T) { @@ -157,8 +157,8 @@ func TestIntegration_GetAdminStats(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - store, cfg := db.InitTestReplDBWithCfg(t) - statsService := ProvideService(cfg, store) + db, cfg := db.InitTestDBWithCfg(t) + statsService := ProvideService(cfg, db) query := stats.GetAdminStatsQuery{} _, err := statsService.GetAdminStats(context.Background(), &query) diff --git a/pkg/services/team/teamimpl/store.go b/pkg/services/team/teamimpl/store.go index 8d3b0a068ed..e1069cd9f4e 100644 --- a/pkg/services/team/teamimpl/store.go +++ b/pkg/services/team/teamimpl/store.go @@ -31,7 +31,7 @@ type store interface { } type xormStore struct { - db db.ReplDB + db db.DB cfg *setting.Cfg deletes []string } @@ -84,7 +84,7 @@ func (ss *xormStore) Create(name, email string, orgID int64) (team.Team, error) Created: time.Now(), Updated: time.Now(), } - err := ss.db.DB().WithTransactionalDbSession(context.Background(), func(sess *db.Session) error { + err := ss.db.WithTransactionalDbSession(context.Background(), func(sess *db.Session) error { if isNameTaken, err := isTeamNameTaken(orgID, name, 0, sess); err != nil { return err } else if isNameTaken { @@ -98,7 +98,7 @@ func (ss *xormStore) Create(name, email string, orgID int64) (team.Team, error) } func (ss *xormStore) Update(ctx context.Context, cmd *team.UpdateTeamCommand) error { - return ss.db.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { + return ss.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error { if isNameTaken, err := isTeamNameTaken(cmd.OrgID, cmd.Name, cmd.ID, sess); err != nil { return err } else if isNameTaken { @@ -129,7 +129,7 @@ func (ss *xormStore) Update(ctx context.Context, cmd *team.UpdateTeamCommand) er // DeleteTeam will delete a team, its member and any permissions connected to the team func (ss *xormStore) Delete(ctx context.Context, cmd *team.DeleteTeamCommand) error { - return ss.db.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { + return ss.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error { if _, err := teamExists(cmd.OrgID, cmd.ID, sess); err != nil { return err } @@ -180,7 +180,7 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) ( queryResult := team.SearchTeamQueryResult{ Teams: make([]*team.TeamDTO, 0), } - err := ss.db.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { + err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { queryWithWildcards := "%" + query.Query + "%" var sql bytes.Buffer @@ -191,12 +191,12 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) ( params = append(params, user) } - sql.WriteString(getTeamSelectSQLBase(ss.db.ReadReplica(), filteredUsers)) + sql.WriteString(getTeamSelectSQLBase(ss.db, filteredUsers)) sql.WriteString(` WHERE team.org_id = ?`) params = append(params, query.OrgID) if query.Query != "" { - sql.WriteString(` and team.name ` + ss.db.ReadReplica().GetDialect().LikeStr() + ` ?`) + sql.WriteString(` and team.name ` + ss.db.GetDialect().LikeStr() + ` ?`) params = append(params, queryWithWildcards) } @@ -233,7 +233,7 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) ( if query.Limit != 0 { offset := query.Limit * (query.Page - 1) - sql.WriteString(ss.db.ReadReplica().GetDialect().LimitOffset(int64(query.Limit), int64(offset))) + sql.WriteString(ss.db.GetDialect().LimitOffset(int64(query.Limit), int64(offset))) } if err := sess.SQL(sql.String(), params...).Find(&queryResult.Teams); err != nil { @@ -245,7 +245,7 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) ( countSess.Where("team.org_id=?", query.OrgID) if query.Query != "" { - countSess.Where(`name `+ss.db.ReadReplica().GetDialect().LikeStr()+` ?`, queryWithWildcards) + countSess.Where(`name `+ss.db.GetDialect().LikeStr()+` ?`, queryWithWildcards) } if query.Name != "" { @@ -268,12 +268,12 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) ( func (ss *xormStore) GetByID(ctx context.Context, query *team.GetTeamByIDQuery) (*team.TeamDTO, error) { var queryResult *team.TeamDTO - err := ss.db.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { + err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { var sql bytes.Buffer params := make([]any, 0) filteredUsers := getFilteredUsers(query.SignedInUser, query.HiddenUsers) - sql.WriteString(getTeamSelectSQLBase(ss.db.ReadReplica(), filteredUsers)) + sql.WriteString(getTeamSelectSQLBase(ss.db, filteredUsers)) for _, user := range filteredUsers { params = append(params, user) } @@ -304,12 +304,12 @@ func (ss *xormStore) GetByID(ctx context.Context, query *team.GetTeamByIDQuery) // GetTeamsByUser is used by the Guardian when checking a users' permissions func (ss *xormStore) GetByUser(ctx context.Context, query *team.GetTeamsByUserQuery) ([]*team.TeamDTO, error) { queryResult := make([]*team.TeamDTO, 0) - err := ss.db.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { + err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { var sql bytes.Buffer var params []any params = append(params, query.OrgID, query.UserID) - sql.WriteString(getTeamSelectSQLBase(ss.db.ReadReplica(), []string{})) + sql.WriteString(getTeamSelectSQLBase(ss.db, []string{})) sql.WriteString(` INNER JOIN team_member on team.id = team_member.team_id`) sql.WriteString(` WHERE team.org_id = ? and team_member.user_id = ?`) @@ -333,7 +333,7 @@ func (ss *xormStore) GetByUser(ctx context.Context, query *team.GetTeamsByUserQu func (ss *xormStore) GetIDsByUser(ctx context.Context, query *team.GetTeamIDsByUserQuery) ([]int64, error) { queryResult := make([]int64, 0) - err := ss.db.ReadReplica().WithDbSession(ctx, func(sess *db.Session) error { + err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { return sess.SQL(`SELECT tm.team_id FROM team_member as tm WHERE tm.user_id=? AND tm.org_id=?;`, query.UserID, query.OrgID).Find(&queryResult) @@ -363,7 +363,7 @@ func getTeamMember(sess *db.Session, orgId int64, teamId int64, userId int64) (t func (ss *xormStore) IsMember(orgId int64, teamId int64, userId int64) (bool, error) { var isMember bool - err := ss.db.ReadReplica().WithDbSession(context.Background(), func(sess *db.Session) error { + err := ss.db.WithDbSession(context.Background(), func(sess *db.Session) error { var err error isMember, err = isTeamMember(sess, orgId, teamId, userId) return err @@ -460,7 +460,7 @@ func removeTeamMember(sess *db.Session, cmd *team.RemoveTeamMemberCommand) error // RemoveUsersMemberships removes all the team membership entries for the given user. // Only used when removing a user from a Grafana instance. func (ss *xormStore) RemoveUsersMemberships(ctx context.Context, userID int64) error { - return ss.db.DB().WithTransactionalDbSession(ctx, func(sess *db.Session) error { + return ss.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error { var rawSQL = "DELETE FROM team_member WHERE user_id = ?" _, err := sess.Exec(rawSQL, userID) return err @@ -488,7 +488,7 @@ func (ss *xormStore) GetMembers(ctx context.Context, query *team.GetTeamMembersQ // With accesscontrol we filter out users based on the SignedInUser's permissions // Note we assume that checking SignedInUser is allowed to see team members for this team has already been performed // If the signed in user is not set no member will be returned - sqlID := fmt.Sprintf("%s.%s", ss.db.ReadReplica().GetDialect().Quote("user"), ss.db.ReadReplica().GetDialect().Quote("id")) + sqlID := fmt.Sprintf("%s.%s", ss.db.GetDialect().Quote("user"), ss.db.GetDialect().Quote("id")) *acFilter, err = ac.Filter(query.SignedInUser, sqlID, "users:id:", ac.ActionOrgUsersRead) if err != nil { return nil, err @@ -500,16 +500,15 @@ func (ss *xormStore) GetMembers(ctx context.Context, query *team.GetTeamMembersQ // getTeamMembers return a list of members for the specified team func (ss *xormStore) getTeamMembers(ctx context.Context, query *team.GetTeamMembersQuery, acUserFilter *ac.SQLFilter) ([]*team.TeamMemberDTO, error) { queryResult := make([]*team.TeamMemberDTO, 0) - err := ss.db.ReadReplica().WithDbSession(ctx, func(dbSess *db.Session) error { - dialect := ss.db.ReadReplica().GetDialect() + err := ss.db.WithDbSession(ctx, func(dbSess *db.Session) error { sess := dbSess.Table("team_member") - sess.Join("INNER", dialect.Quote("user"), - fmt.Sprintf("team_member.user_id=%s.%s", dialect.Quote("user"), dialect.Quote("id")), + sess.Join("INNER", ss.db.GetDialect().Quote("user"), + fmt.Sprintf("team_member.user_id=%s.%s", ss.db.GetDialect().Quote("user"), ss.db.GetDialect().Quote("id")), ) sess.Join("INNER", "team", "team.id=team_member.team_id") // explicitly check for serviceaccounts - sess.Where(fmt.Sprintf("%s.is_service_account=?", dialect.Quote("user")), dialect.BooleanStr(false)) + sess.Where(fmt.Sprintf("%s.is_service_account=?", ss.db.GetDialect().Quote("user")), ss.db.GetDialect().BooleanStr(false)) if acUserFilter != nil { sess.Where(acUserFilter.Where, acUserFilter.Args...) @@ -521,7 +520,7 @@ func (ss *xormStore) getTeamMembers(ctx context.Context, query *team.GetTeamMemb FROM user_auth WHERE user_auth.user_id = team_member.user_id ORDER BY user_auth.created DESC ` + - dialect.Limit(1) + ")" + ss.db.GetDialect().Limit(1) + ")" sess.Join("LEFT", "user_auth", authJoinCondition) if query.OrgID != 0 { @@ -537,7 +536,7 @@ func (ss *xormStore) getTeamMembers(ctx context.Context, query *team.GetTeamMemb sess.Where("team_member.user_id=?", query.UserID) } if query.External { - sess.Where("team_member.external=?", dialect.BooleanStr(true)) + sess.Where("team_member.external=?", ss.db.GetDialect().BooleanStr(true)) } sess.Cols( "team_member.org_id", diff --git a/pkg/services/team/teamimpl/store_test.go b/pkg/services/team/teamimpl/store_test.go index 1041bdb86ed..066cc02b13e 100644 --- a/pkg/services/team/teamimpl/store_test.go +++ b/pkg/services/team/teamimpl/store_test.go @@ -16,7 +16,6 @@ import ( "github.com/grafana/grafana/pkg/services/org/orgimpl" "github.com/grafana/grafana/pkg/services/quota/quotaimpl" "github.com/grafana/grafana/pkg/services/serviceaccounts" - "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest" "github.com/grafana/grafana/pkg/services/team" "github.com/grafana/grafana/pkg/services/team/sortopts" @@ -35,7 +34,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) { t.Skip("skipping integration test") } t.Run("Testing Team commands and queries", func(t *testing.T) { - sqlStore, cfg := db.InitTestReplDBWithCfg(t) + sqlStore, cfg := db.InitTestDBWithCfg(t) teamSvc, err := ProvideService(sqlStore, cfg, tracing.InitializeTracerForTest()) require.NoError(t, err) testUser := &user.SignedInUser{ @@ -48,7 +47,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) { }, }, } - quotaService := quotaimpl.ProvideService(sqlstore.FakeReplStoreFromStore(sqlStore.SQLStore), cfg) + quotaService := quotaimpl.ProvideService(sqlStore, cfg) orgSvc, err := orgimpl.ProvideService(sqlStore, cfg, quotaService) require.NoError(t, err) userSvc, err := userimpl.ProvideService( @@ -148,7 +147,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) { }) t.Run("Should return latest auth module for users when getting team members", func(t *testing.T) { - sqlStore = db.InitTestReplDB(t) + sqlStore = db.InitTestDB(t) setup() userId := userIds[1] @@ -199,7 +198,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) { }) t.Run("Should default to member permission level when updating a user with invalid permission level", func(t *testing.T) { - sqlStore = db.InitTestReplDB(t) + sqlStore = db.InitTestDB(t) setup() userID := userIds[0] @@ -313,7 +312,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) { }) t.Run("Should be able to return all teams a user is member of", func(t *testing.T) { - sqlStore = db.InitTestReplDB(t) + sqlStore = db.InitTestDB(t) setup() groupId := team2.ID err = sqlStore.WithDbSession(context.Background(), func(sess *db.Session) error { @@ -374,7 +373,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) { }) t.Run("A user should be able to remove the admin permission if there are other admins", func(t *testing.T) { - sqlStore = db.InitTestReplDB(t) + sqlStore = db.InitTestDB(t) setup() err = sqlStore.WithDbSession(context.Background(), func(sess *db.Session) error { @@ -393,7 +392,7 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) { }) t.Run("Should not return hidden users in team member count", func(t *testing.T) { - sqlStore = db.InitTestReplDB(t) + sqlStore = db.InitTestDB(t) setup() signedInUser := &user.SignedInUser{ Login: "loginuser0", @@ -434,8 +433,8 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) { }) t.Run("Should be able to exclude service accounts from teamembers", func(t *testing.T) { - sqlStore = db.InitTestReplDB(t) - quotaService := quotaimpl.ProvideService(sqlstore.FakeReplStoreFromStore(sqlStore.SQLStore), cfg) + sqlStore = db.InitTestDB(t) + quotaService := quotaimpl.ProvideService(sqlStore, cfg) orgSvc, err := orgimpl.ProvideService(sqlStore, cfg, quotaService) require.NoError(t, err) userSvc, err := userimpl.ProvideService( @@ -529,7 +528,7 @@ func TestIntegrationSQLStore_SearchTeams(t *testing.T) { }, } - store, cfg := db.InitTestReplDBWithCfg(t, db.InitTestDBOpt{}) + store, cfg := db.InitTestDBWithCfg(t, db.InitTestDBOpt{}) teamSvc, err := ProvideService(store, cfg, tracing.InitializeTracerForTest()) require.NoError(t, err) @@ -566,18 +565,18 @@ func TestIntegrationSQLStore_GetTeamMembers_ACFilter(t *testing.T) { userIds := make([]int64, 4) // Seed 2 teams with 2 members - setup := func(store db.ReplDB, cfg *setting.Cfg) { + setup := func(store db.DB, cfg *setting.Cfg) { teamSvc, err := ProvideService(store, cfg, tracing.InitializeTracerForTest()) require.NoError(t, err) team1, errCreateTeam := teamSvc.CreateTeam(context.Background(), "group1 name", "test1@example.org", testOrgID) require.NoError(t, errCreateTeam) team2, errCreateTeam := teamSvc.CreateTeam(context.Background(), "group2 name", "test2@example.org", testOrgID) require.NoError(t, errCreateTeam) - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(store.DB()), cfg) - orgSvc, err := orgimpl.ProvideService(store.DB(), cfg, quotaService) + quotaService := quotaimpl.ProvideService(store, cfg) + orgSvc, err := orgimpl.ProvideService(store, cfg, quotaService) require.NoError(t, err) userSvc, err := userimpl.ProvideService( - store.DB(), orgSvc, cfg, teamSvc, nil, tracing.InitializeTracerForTest(), + store, orgSvc, cfg, teamSvc, nil, tracing.InitializeTracerForTest(), quotaService, supportbundlestest.NewFakeBundleService(), ) require.NoError(t, err) @@ -593,7 +592,7 @@ func TestIntegrationSQLStore_GetTeamMembers_ACFilter(t *testing.T) { userIds[i] = user.ID } - errAddMembers := store.DB().WithDbSession(context.Background(), func(sess *db.Session) error { + errAddMembers := store.WithDbSession(context.Background(), func(sess *db.Session) error { err := AddOrUpdateTeamMemberHook(sess, userIds[0], testOrgID, team1.ID, false, 0) if err != nil { return err @@ -611,7 +610,7 @@ func TestIntegrationSQLStore_GetTeamMembers_ACFilter(t *testing.T) { require.NoError(t, errAddMembers) } - store, cfg := db.InitTestReplDBWithCfg(t, db.InitTestDBOpt{}) + store, cfg := db.InitTestDBWithCfg(t, db.InitTestDBOpt{}) setup(store, cfg) teamSvc, err := ProvideService(store, cfg, tracing.InitializeTracerForTest()) require.NoError(t, err) diff --git a/pkg/services/team/teamimpl/team.go b/pkg/services/team/teamimpl/team.go index 14212f22b7f..e7c9537b751 100644 --- a/pkg/services/team/teamimpl/team.go +++ b/pkg/services/team/teamimpl/team.go @@ -17,7 +17,7 @@ type Service struct { tracer tracing.Tracer } -func ProvideService(db db.ReplDB, cfg *setting.Cfg, tracer tracing.Tracer) (team.Service, error) { +func ProvideService(db db.DB, cfg *setting.Cfg, tracer tracing.Tracer) (team.Service, error) { return &Service{ store: &xormStore{db: db, cfg: cfg, deletes: []string{}}, tracer: tracer, diff --git a/pkg/services/user/userimpl/store_test.go b/pkg/services/user/userimpl/store_test.go index 86f38407821..45ed734c2f7 100644 --- a/pkg/services/user/userimpl/store_test.go +++ b/pkg/services/user/userimpl/store_test.go @@ -34,7 +34,7 @@ func TestIntegrationUserDataAccess(t *testing.T) { } ss, cfg := db.InitTestDBWithCfg(t) - quotaService := quotaimpl.ProvideService(sqlstore.FakeReplStoreFromStore(ss), cfg) + quotaService := quotaimpl.ProvideService(ss, cfg) orgService, err := orgimpl.ProvideService(ss, cfg, quotaService) require.NoError(t, err) userStore := ProvideStore(ss, setting.NewCfg()) @@ -903,7 +903,7 @@ func createFiveTestUsers(t *testing.T, svc user.Service, fn func(i int) *user.Cr func TestMetricsUsage(t *testing.T) { ss, cfg := db.InitTestDBWithCfg(t) userStore := ProvideStore(ss, setting.NewCfg()) - quotaService := quotaimpl.ProvideService(sqlstore.FakeReplStoreFromStore(ss), cfg) + quotaService := quotaimpl.ProvideService(ss, cfg) orgService, err := orgimpl.ProvideService(ss, cfg, quotaService) require.NoError(t, err) @@ -962,7 +962,7 @@ func assertEqualUser(t *testing.T, expected, got *user.User) { func createOrgAndUserSvc(t *testing.T, store db.DB, cfg *setting.Cfg) (org.Service, user.Service) { t.Helper() - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(store), cfg) + quotaService := quotaimpl.ProvideService(store, cfg) orgService, err := orgimpl.ProvideService(store, cfg, quotaService) require.NoError(t, err) usrSvc, err := ProvideService( diff --git a/pkg/tests/api/alerting/api_alertmanager_test.go b/pkg/tests/api/alerting/api_alertmanager_test.go index 9a943e1b1f8..e5d7b5fb01f 100644 --- a/pkg/tests/api/alerting/api_alertmanager_test.go +++ b/pkg/tests/api/alerting/api_alertmanager_test.go @@ -2691,17 +2691,17 @@ func rulesNamespaceWithoutVariableValues(t *testing.T, b []byte) (string, map[st return string(json), m } -func createUser(t *testing.T, store db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) int64 { +func createUser(t *testing.T, db db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) int64 { t.Helper() cfg.AutoAssignOrg = true cfg.AutoAssignOrgId = 1 - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(store), cfg) - orgService, err := orgimpl.ProvideService(store, cfg, quotaService) + quotaService := quotaimpl.ProvideService(db, cfg) + orgService, err := orgimpl.ProvideService(db, cfg, quotaService) require.NoError(t, err) usrSvc, err := userimpl.ProvideService( - store, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), + db, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), quotaService, supportbundlestest.NewFakeBundleService(), ) require.NoError(t, err) diff --git a/pkg/tests/api/correlations/common_test.go b/pkg/tests/api/correlations/common_test.go index efb707841de..2bd291db9e8 100644 --- a/pkg/tests/api/correlations/common_test.go +++ b/pkg/tests/api/correlations/common_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/server" "github.com/grafana/grafana/pkg/services/correlations" @@ -145,7 +144,7 @@ func (c TestContext) createOrg(name string) int64 { c.t.Helper() store := c.env.SQLStore c.env.Cfg.AutoAssignOrg = false - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(store), c.env.Cfg) + quotaService := quotaimpl.ProvideService(store, c.env.Cfg) orgService, err := orgimpl.ProvideService(store, c.env.Cfg, quotaService) require.NoError(c.t, err) orgId, err := orgService.GetOrCreate(context.Background(), name) @@ -159,7 +158,7 @@ func (c TestContext) createUser(cmd user.CreateUserCommand) User { c.env.Cfg.AutoAssignOrg = true c.env.Cfg.AutoAssignOrgId = 1 - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(store), c.env.Cfg) + quotaService := quotaimpl.ProvideService(store, c.env.Cfg) orgService, err := orgimpl.ProvideService(store, c.env.Cfg, quotaService) require.NoError(c.t, err) usrSvc, err := userimpl.ProvideService( diff --git a/pkg/tests/api/dashboards/api_dashboards_test.go b/pkg/tests/api/dashboards/api_dashboards_test.go index f3a6d3c1a23..604f0df60b8 100644 --- a/pkg/tests/api/dashboards/api_dashboards_test.go +++ b/pkg/tests/api/dashboards/api_dashboards_test.go @@ -115,17 +115,17 @@ func TestIntegrationDashboardQuota(t *testing.T) { }) } -func createUser(t *testing.T, store db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) int64 { +func createUser(t *testing.T, db db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) int64 { t.Helper() cfg.AutoAssignOrg = true cfg.AutoAssignOrgId = 1 - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(store), cfg) - orgService, err := orgimpl.ProvideService(store, cfg, quotaService) + quotaService := quotaimpl.ProvideService(db, cfg) + orgService, err := orgimpl.ProvideService(db, cfg, quotaService) require.NoError(t, err) usrSvc, err := userimpl.ProvideService( - store, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), + db, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), quotaService, supportbundlestest.NewFakeBundleService(), ) require.NoError(t, err) diff --git a/pkg/tests/api/folders/api_folder_test.go b/pkg/tests/api/folders/api_folder_test.go index dcb2ef7e28c..c61e94b0cd9 100644 --- a/pkg/tests/api/folders/api_folder_test.go +++ b/pkg/tests/api/folders/api_folder_test.go @@ -9,9 +9,6 @@ import ( "github.com/go-openapi/runtime" "github.com/grafana/grafana-openapi-client-go/client/folders" "github.com/grafana/grafana-openapi-client-go/models" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/services/featuremgmt" @@ -24,6 +21,8 @@ import ( "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/tests" "github.com/grafana/grafana/pkg/tests/testinfra" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const orgID = 1 @@ -208,17 +207,17 @@ func TestIntegrationNestedFoldersOn(t *testing.T) { }) } -func createUser(t *testing.T, store db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) int64 { +func createUser(t *testing.T, db db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) int64 { t.Helper() cfg.AutoAssignOrg = true cfg.AutoAssignOrgId = orgID - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(store), cfg) - orgService, err := orgimpl.ProvideService(store, cfg, quotaService) + quotaService := quotaimpl.ProvideService(db, cfg) + orgService, err := orgimpl.ProvideService(db, cfg, quotaService) require.NoError(t, err) usrSvc, err := userimpl.ProvideService( - store, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), + db, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), quotaService, supportbundlestest.NewFakeBundleService(), ) require.NoError(t, err) diff --git a/pkg/tests/api/plugins/api_plugins_test.go b/pkg/tests/api/plugins/api_plugins_test.go index cfdd8851692..ba04251c1fb 100644 --- a/pkg/tests/api/plugins/api_plugins_test.go +++ b/pkg/tests/api/plugins/api_plugins_test.go @@ -193,17 +193,17 @@ func TestIntegrationPluginAssets(t *testing.T) { }) } -func createUser(t *testing.T, store db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) { +func createUser(t *testing.T, db db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) { t.Helper() cfg.AutoAssignOrg = true cfg.AutoAssignOrgId = 1 - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(store), cfg) - orgService, err := orgimpl.ProvideService(store, cfg, quotaService) + quotaService := quotaimpl.ProvideService(db, cfg) + orgService, err := orgimpl.ProvideService(db, cfg, quotaService) require.NoError(t, err) usrSvc, err := userimpl.ProvideService( - store, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), + db, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), quotaService, supportbundlestest.NewFakeBundleService(), ) require.NoError(t, err) diff --git a/pkg/tests/api/stats/admin_test.go b/pkg/tests/api/stats/admin_test.go index eb65250778c..3e264a75e0c 100644 --- a/pkg/tests/api/stats/admin_test.go +++ b/pkg/tests/api/stats/admin_test.go @@ -81,17 +81,17 @@ func grafanaSetup(t *testing.T, opts testinfra.GrafanaOpts) string { return fmt.Sprintf("http://%s:%s@%s/api/admin/stats", "grafana", "password", grafanaListedAddr) } -func createUser(t *testing.T, store db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) int64 { +func createUser(t *testing.T, db db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) int64 { t.Helper() cfg.AutoAssignOrg = true cfg.AutoAssignOrgId = 1 - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(store), cfg) - orgService, err := orgimpl.ProvideService(store, cfg, quotaService) + quotaService := quotaimpl.ProvideService(db, cfg) + orgService, err := orgimpl.ProvideService(db, cfg, quotaService) require.NoError(t, err) usrSvc, err := userimpl.ProvideService( - store, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), + db, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), quotaService, supportbundlestest.NewFakeBundleService(), ) require.NoError(t, err) diff --git a/pkg/tests/apis/helper.go b/pkg/tests/apis/helper.go index eaa24a5b228..12f1aa512ed 100644 --- a/pkg/tests/apis/helper.go +++ b/pkg/tests/apis/helper.go @@ -20,6 +20,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer/yaml" yamlutil "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/client-go/discovery" "k8s.io/client-go/dynamic" "k8s.io/client-go/rest" @@ -437,13 +438,12 @@ func (c *K8sTestHelper) CreateUser(name string, orgName string, basicRole org.Ro c.t.Helper() store := c.env.SQLStore - replStore := c.env.ReadReplStore defer func() { c.env.Cfg.AutoAssignOrg = false c.env.Cfg.AutoAssignOrgId = 1 // the default }() - quotaService := quotaimpl.ProvideService(replStore, c.env.Cfg) + quotaService := quotaimpl.ProvideService(store, c.env.Cfg) orgService, err := orgimpl.ProvideService(store, c.env.Cfg, quotaService) require.NoError(c.t, err) @@ -464,7 +464,7 @@ func (c *K8sTestHelper) CreateUser(name string, orgName string, basicRole org.Ro c.env.Cfg.AutoAssignOrg = true c.env.Cfg.AutoAssignOrgId = int(orgId) - teamSvc, err := teamimpl.ProvideService(replStore, c.env.Cfg, tracing.InitializeTracerForTest()) + teamSvc, err := teamimpl.ProvideService(store, c.env.Cfg, tracing.InitializeTracerForTest()) require.NoError(c.t, err) cache := localcache.ProvideService() @@ -533,7 +533,7 @@ func (c *K8sTestHelper) SetPermissions(user User, permissions []resourcepermissi } func (c *K8sTestHelper) AddOrUpdateTeamMember(user User, teamID int64, permission team.PermissionType) { - teamSvc, err := teamimpl.ProvideService(c.env.ReadReplStore, c.env.Cfg, tracing.InitializeTracerForTest()) + teamSvc, err := teamimpl.ProvideService(c.env.SQLStore, c.env.Cfg, tracing.InitializeTracerForTest()) require.NoError(c.t, err) orgService, err := orgimpl.ProvideService(c.env.SQLStore, c.env.Cfg, c.env.Server.HTTPServer.QuotaService) diff --git a/pkg/tests/testinfra/testinfra.go b/pkg/tests/testinfra/testinfra.go index 9f6f5a0220b..8468cb154e2 100644 --- a/pkg/tests/testinfra/testinfra.go +++ b/pkg/tests/testinfra/testinfra.go @@ -498,7 +498,7 @@ func CreateUser(t *testing.T, store db.DB, cfg *setting.Cfg, cmd user.CreateUser cfg.AutoAssignOrgId = 1 cmd.OrgID = 1 - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(store), cfg) + quotaService := quotaimpl.ProvideService(store, cfg) orgService, err := orgimpl.ProvideService(store, cfg, quotaService) require.NoError(t, err) usrSvc, err := userimpl.ProvideService( diff --git a/pkg/tests/utils.go b/pkg/tests/utils.go index c1208211e95..f81683c80f4 100644 --- a/pkg/tests/utils.go +++ b/pkg/tests/utils.go @@ -9,8 +9,6 @@ import ( "github.com/go-openapi/strfmt" goapi "github.com/grafana/grafana-openapi-client-go/client" - "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions" @@ -21,19 +19,20 @@ import ( "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user/userimpl" "github.com/grafana/grafana/pkg/setting" + "github.com/stretchr/testify/require" ) -func CreateUser(t *testing.T, store db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) int64 { +func CreateUser(t *testing.T, db db.DB, cfg *setting.Cfg, cmd user.CreateUserCommand) int64 { t.Helper() cfg.AutoAssignOrg = true cfg.AutoAssignOrgId = 1 - quotaService := quotaimpl.ProvideService(db.FakeReplDBFromDB(store), cfg) - orgService, err := orgimpl.ProvideService(store, cfg, quotaService) + quotaService := quotaimpl.ProvideService(db, cfg) + orgService, err := orgimpl.ProvideService(db, cfg, quotaService) require.NoError(t, err) usrSvc, err := userimpl.ProvideService( - store, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), + db, orgService, cfg, nil, nil, tracing.InitializeTracerForTest(), quotaService, supportbundlestest.NewFakeBundleService(), ) require.NoError(t, err)