From 7b4cea8151e27c1ccaca1d1577958f5daf0e03f1 Mon Sep 17 00:00:00 2001 From: ying-jeanne <74549700+ying-jeanne@users.noreply.github.com> Date: Wed, 21 Sep 2022 14:04:01 +0200 Subject: [PATCH] Chore: StoreSplit tag service (#55453) * move tag service outside * fix dashboard * fix test * lint * fix linter * remove spew --- pkg/api/annotations.go | 2 +- pkg/api/common_test.go | 3 +- pkg/api/dashboard.go | 6 +- pkg/api/dashboard_test.go | 5 +- pkg/api/http_server.go | 5 +- pkg/api/org_users_test.go | 2 +- pkg/cmd/grafana-cli/runner/wire.go | 4 + pkg/models/alert.go | 7 +- pkg/models/alert_test.go | 3 +- pkg/server/wire.go | 4 + .../alerting/notifiers/opsgenie_test.go | 7 +- .../alerting/notifiers/pagerduty_test.go | 7 +- .../alerting/notifiers/victorops_test.go | 5 +- pkg/services/alerting/rule.go | 3 +- pkg/services/alerting/store.go | 27 ++-- pkg/services/alerting/store_test.go | 13 +- .../annotationsimpl/annotations.go | 10 +- .../annotations/annotationsimpl/xorm_store.go | 40 +++-- .../annotationsimpl/xorm_store_test.go | 20 +-- pkg/services/dashboards/dashboard.go | 18 +-- .../dashboards/dashboard_provisioning_mock.go | 6 +- pkg/services/dashboards/database/acl_test.go | 3 +- pkg/services/dashboards/database/database.go | 149 ++++++++---------- .../database/database_folder_test.go | 15 +- .../database/database_provisioning_test.go | 19 +-- .../dashboards/database/database_test.go | 23 +-- .../dashboards/service/dashboard_service.go | 26 +-- .../dashboard_service_integration_test.go | 11 +- .../dashboards/service/folder_service.go | 4 +- pkg/services/dashboards/store_mock.go | 12 +- .../guardian/accesscontrol_guardian_test.go | 5 +- .../libraryelements/libraryelements_test.go | 7 +- .../librarypanels/librarypanels_test.go | 7 +- pkg/services/ngalert/tests/util.go | 3 +- .../provisioning/dashboards/file_reader.go | 6 +- pkg/services/publicdashboards/api/api_test.go | 5 +- .../database/database_test.go | 13 +- .../publicdashboards/service/service_test.go | 19 +-- pkg/services/sqlstore/session.go | 7 - pkg/services/sqlstore/tags.go | 26 --- pkg/{models/tags.go => services/tag/model.go} | 4 +- .../tag/model_test.go} | 2 +- pkg/services/tag/tag.go | 9 ++ pkg/services/tag/tagimpl/store.go | 39 +++++ .../tagimpl/store_test.go} | 13 +- pkg/services/tag/tagimpl/tag.go | 24 +++ 46 files changed, 355 insertions(+), 293 deletions(-) delete mode 100644 pkg/services/sqlstore/tags.go rename pkg/{models/tags.go => services/tag/model.go} (95%) rename pkg/{models/tags_test.go => services/tag/model_test.go} (99%) create mode 100644 pkg/services/tag/tag.go create mode 100644 pkg/services/tag/tagimpl/store.go rename pkg/services/{sqlstore/tags_test.go => tag/tagimpl/store_test.go} (57%) create mode 100644 pkg/services/tag/tagimpl/tag.go diff --git a/pkg/api/annotations.go b/pkg/api/annotations.go index 145d294d930..0b981d91b54 100644 --- a/pkg/api/annotations.go +++ b/pkg/api/annotations.go @@ -228,7 +228,7 @@ func (hs *HTTPServer) PostGraphiteAnnotation(c *models.ReqContext) response.Resp Tags: tagsArray, } - if err := hs.annotationsRepo.Save(context.Background(), &item); err != nil { + if err := hs.annotationsRepo.Save(c.Req.Context(), &item); err != nil { return response.Error(500, "Failed to save Graphite annotation", err) } diff --git a/pkg/api/common_test.go b/pkg/api/common_test.go index 838a24b102d..5542fc7bade 100644 --- a/pkg/api/common_test.go +++ b/pkg/api/common_test.go @@ -51,6 +51,7 @@ import ( "github.com/grafana/grafana/pkg/services/searchusers/filters" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore/mockstore" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/team" "github.com/grafana/grafana/pkg/services/team/teamimpl" "github.com/grafana/grafana/pkg/services/team/teamtest" @@ -371,7 +372,7 @@ func setupHTTPServerWithCfgDb( license := &licensing.OSSLicensingService{} routeRegister := routing.NewRouteRegister() teamService := teamimpl.ProvideService(db) - dashboardsStore := dashboardsstore.ProvideDashboardStore(db, featuremgmt.WithFeatures()) + dashboardsStore := dashboardsstore.ProvideDashboardStore(db, featuremgmt.WithFeatures(), tagimpl.ProvideService(db)) var acmock *accesscontrolmock.Mock var ac accesscontrol.AccessControl diff --git a/pkg/api/dashboard.go b/pkg/api/dashboard.go index 355857ca52e..40d865e3a99 100644 --- a/pkg/api/dashboard.go +++ b/pkg/api/dashboard.go @@ -189,7 +189,7 @@ func (hs *HTTPServer) GetDashboard(c *models.ReqContext) response.Response { meta.FolderUrl = query.Result.GetUrl() } - provisioningData, err := hs.dashboardProvisioningService.GetProvisionedDashboardDataByDashboardID(dash.Id) + provisioningData, err := hs.dashboardProvisioningService.GetProvisionedDashboardDataByDashboardID(c.Req.Context(), dash.Id) if err != nil { return response.Error(500, "Error while checking if dashboard is provisioned", err) } @@ -407,13 +407,13 @@ func (hs *HTTPServer) postDashboard(c *models.ReqContext, cmd models.SaveDashboa var provisioningData *models.DashboardProvisioning if dash.Id != 0 { - data, err := hs.dashboardProvisioningService.GetProvisionedDashboardDataByDashboardID(dash.Id) + data, err := hs.dashboardProvisioningService.GetProvisionedDashboardDataByDashboardID(c.Req.Context(), dash.Id) if err != nil { return response.Error(500, "Error while checking if dashboard is provisioned using ID", err) } provisioningData = data } else if dash.Uid != "" { - data, err := hs.dashboardProvisioningService.GetProvisionedDashboardDataByDashboardUID(dash.OrgId, dash.Uid) + data, err := hs.dashboardProvisioningService.GetProvisionedDashboardDataByDashboardUID(c.Req.Context(), dash.OrgId, dash.Uid) if err != nil && !errors.Is(err, dashboards.ErrProvisionedDashboardNotFound) && !errors.Is(err, dashboards.ErrDashboardNotFound) { return response.Error(500, "Error while checking if dashboard is provisioned", err) } diff --git a/pkg/api/dashboard_test.go b/pkg/api/dashboard_test.go index ffa8d59dc08..57f57c79a82 100644 --- a/pkg/api/dashboard_test.go +++ b/pkg/api/dashboard_test.go @@ -39,6 +39,7 @@ import ( "github.com/grafana/grafana/pkg/services/quota/quotaimpl" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore/mockstore" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/team/teamtest" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" @@ -935,7 +936,7 @@ func getDashboardShouldReturn200WithConfig(t *testing.T, sc *scenarioContext, pr if dashboardStore == nil { sql := sqlstore.InitTestDB(t) - dashboardStore = database.ProvideDashboardStore(sql, featuremgmt.WithFeatures()) + dashboardStore = database.ProvideDashboardStore(sql, featuremgmt.WithFeatures(), tagimpl.ProvideService(sql)) } libraryPanelsService := mockLibraryPanelService{} @@ -1140,7 +1141,7 @@ type mockDashboardProvisioningService struct { dashboards.DashboardProvisioningService } -func (s mockDashboardProvisioningService) GetProvisionedDashboardDataByDashboardID(dashboardID int64) ( +func (s mockDashboardProvisioningService) GetProvisionedDashboardDataByDashboardID(ctx context.Context, dashboardID int64) ( *models.DashboardProvisioning, error) { return nil, nil } diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index 965addec765..8350e0db3e4 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -84,6 +84,7 @@ import ( "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/star" "github.com/grafana/grafana/pkg/services/store" + "github.com/grafana/grafana/pkg/services/tag" "github.com/grafana/grafana/pkg/services/team" "github.com/grafana/grafana/pkg/services/teamguardian" tempUser "github.com/grafana/grafana/pkg/services/temp_user" @@ -193,6 +194,7 @@ type HTTPServer struct { teamService team.Service accesscontrolService accesscontrol.Service annotationsRepo annotations.Repository + tagService tag.Service } type ServerOptions struct { @@ -232,7 +234,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi secretsPluginMigrator spm.SecretMigrationProvider, secretsStore secretsKV.SecretsKVStore, publicDashboardsApi *publicdashboardsApi.Api, userService user.Service, tempUserService tempUser.Service, loginAttemptService loginAttempt.Service, orgService org.Service, teamService team.Service, - accesscontrolService accesscontrol.Service, dashboardThumbsService dashboardThumbs.Service, annotationRepo annotations.Repository, + accesscontrolService accesscontrol.Service, dashboardThumbsService dashboardThumbs.Service, annotationRepo annotations.Repository, tagService tag.Service, ) (*HTTPServer, error) { web.Env = cfg.Env m := web.New() @@ -330,6 +332,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi teamService: teamService, accesscontrolService: accesscontrolService, annotationsRepo: annotationRepo, + tagService: tagService, } if hs.Listener != nil { hs.log.Debug("Using provided listener") diff --git a/pkg/api/org_users_test.go b/pkg/api/org_users_test.go index e2b901e41ba..cdfcec8132e 100644 --- a/pkg/api/org_users_test.go +++ b/pkg/api/org_users_test.go @@ -156,7 +156,7 @@ func TestOrgUsersAPIEndpoint_LegacyAccessControl_FolderAdmin(t *testing.T) { "tags": "prod", }), } - folder, err := sc.dashboardsStore.SaveDashboard(cmd) + folder, err := sc.dashboardsStore.SaveDashboard(context.Background(), cmd) require.NoError(t, err) require.NotNil(t, folder) diff --git a/pkg/cmd/grafana-cli/runner/wire.go b/pkg/cmd/grafana-cli/runner/wire.go index 50f067059b8..59422f1e39e 100644 --- a/pkg/cmd/grafana-cli/runner/wire.go +++ b/pkg/cmd/grafana-cli/runner/wire.go @@ -116,6 +116,8 @@ import ( "github.com/grafana/grafana/pkg/services/star/starimpl" "github.com/grafana/grafana/pkg/services/store" "github.com/grafana/grafana/pkg/services/store/sanitizer" + "github.com/grafana/grafana/pkg/services/tag" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/team/teamimpl" "github.com/grafana/grafana/pkg/services/teamguardian" teamguardianDatabase "github.com/grafana/grafana/pkg/services/teamguardian/database" @@ -336,6 +338,8 @@ var wireSet = wire.NewSet( opentsdb.ProvideService, acimpl.ProvideAccessControl, wire.Bind(new(accesscontrol.AccessControl), new(*acimpl.AccessControl)), + tagimpl.ProvideService, + wire.Bind(new(tag.Service), new(*tagimpl.Service)), ) func Initialize(cfg *setting.Cfg) (Runner, error) { diff --git a/pkg/models/alert.go b/pkg/models/alert.go index 30c6badbb03..9d8a8e15f05 100644 --- a/pkg/models/alert.go +++ b/pkg/models/alert.go @@ -5,6 +5,7 @@ import ( "time" "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/services/tag" "github.com/grafana/grafana/pkg/services/user" ) @@ -115,15 +116,15 @@ func (a *Alert) ContainsUpdates(other *Alert) bool { return result } -func (a *Alert) GetTagsFromSettings() []*Tag { - tags := []*Tag{} +func (a *Alert) GetTagsFromSettings() []*tag.Tag { + tags := []*tag.Tag{} if a.Settings != nil { if data, ok := a.Settings.CheckGet("alertRuleTags"); ok { for tagNameString, tagValue := range data.MustMap() { // MustMap() already guarantees the return of a `map[string]interface{}`. // Therefore we only need to verify that tagValue is a String. tagValueString := simplejson.NewFromAny(tagValue).MustString() - tags = append(tags, &Tag{Key: tagNameString, Value: tagValueString}) + tags = append(tags, &tag.Tag{Key: tagNameString, Value: tagValueString}) } } } diff --git a/pkg/models/alert_test.go b/pkg/models/alert_test.go index b2f223e616a..6fb86c9513a 100644 --- a/pkg/models/alert_test.go +++ b/pkg/models/alert_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/services/tag" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -51,7 +52,7 @@ func TestAlert_GetTagsFromSettings(t *testing.T) { Message: "Message", } - expectedTags := []*Tag{ + expectedTags := []*tag.Tag{ {Id: 0, Key: "foo", Value: "bar"}, {Id: 0, Key: "waldo", Value: "fred"}, {Id: 0, Key: "tagMap", Value: ""}, diff --git a/pkg/server/wire.go b/pkg/server/wire.go index 2b241bf51ef..8a07a365bff 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -123,6 +123,8 @@ import ( "github.com/grafana/grafana/pkg/services/sqlstore/mockstore" "github.com/grafana/grafana/pkg/services/star/starimpl" "github.com/grafana/grafana/pkg/services/store" + "github.com/grafana/grafana/pkg/services/tag" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/team/teamimpl" "github.com/grafana/grafana/pkg/services/teamguardian" teamguardianDatabase "github.com/grafana/grafana/pkg/services/teamguardian/database" @@ -349,6 +351,8 @@ var wireBasicSet = wire.NewSet( acimpl.ProvideAccessControl, wire.Bind(new(accesscontrol.AccessControl), new(*acimpl.AccessControl)), wire.Bind(new(notifications.TempUserStore), new(tempuser.Service)), + tagimpl.ProvideService, + wire.Bind(new(tag.Service), new(*tagimpl.Service)), ) var wireSet = wire.NewSet( diff --git a/pkg/services/alerting/notifiers/opsgenie_test.go b/pkg/services/alerting/notifiers/opsgenie_test.go index 7def9ebac72..2f60a6bf5bc 100644 --- a/pkg/services/alerting/notifiers/opsgenie_test.go +++ b/pkg/services/alerting/notifiers/opsgenie_test.go @@ -12,6 +12,7 @@ import ( "github.com/grafana/grafana/pkg/services/annotations/annotationstest" encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service" "github.com/grafana/grafana/pkg/services/notifications" + "github.com/grafana/grafana/pkg/services/tag" "github.com/grafana/grafana/pkg/services/validations" "github.com/stretchr/testify/require" @@ -83,7 +84,7 @@ func TestOpsGenieNotifier(t *testing.T) { "apiKey": "abcdefgh0123456789" }` - tagPairs := []*models.Tag{ + tagPairs := []*tag.Tag{ {Key: "keyOnly"}, {Key: "aKey", Value: "aValue"}, } @@ -132,7 +133,7 @@ func TestOpsGenieNotifier(t *testing.T) { "sendTagsAs": "details" }` - tagPairs := []*models.Tag{ + tagPairs := []*tag.Tag{ {Key: "keyOnly"}, {Key: "aKey", Value: "aValue"}, } @@ -181,7 +182,7 @@ func TestOpsGenieNotifier(t *testing.T) { "sendTagsAs": "both" }` - tagPairs := []*models.Tag{ + tagPairs := []*tag.Tag{ {Key: "keyOnly"}, {Key: "aKey", Value: "aValue"}, } diff --git a/pkg/services/alerting/notifiers/pagerduty_test.go b/pkg/services/alerting/notifiers/pagerduty_test.go index 2fe27ad962b..9e6cf996101 100644 --- a/pkg/services/alerting/notifiers/pagerduty_test.go +++ b/pkg/services/alerting/notifiers/pagerduty_test.go @@ -13,6 +13,7 @@ import ( "github.com/grafana/grafana/pkg/services/alerting" "github.com/grafana/grafana/pkg/services/annotations/annotationstest" encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service" + "github.com/grafana/grafana/pkg/services/tag" "github.com/grafana/grafana/pkg/services/validations" "github.com/stretchr/testify/require" @@ -328,7 +329,7 @@ func TestPagerdutyNotifier(t *testing.T) { Name: "someRule", Message: "someMessage", State: models.AlertStateAlerting, - AlertRuleTags: []*models.Tag{ + AlertRuleTags: []*tag.Tag{ {Key: "keyOnly"}, {Key: "group", Value: "aGroup"}, {Key: "class", Value: "aClass"}, @@ -408,7 +409,7 @@ func TestPagerdutyNotifier(t *testing.T) { Name: "someRule", Message: "someMessage", State: models.AlertStateAlerting, - AlertRuleTags: []*models.Tag{ + AlertRuleTags: []*tag.Tag{ {Key: "keyOnly"}, {Key: "group", Value: "aGroup"}, {Key: "class", Value: "aClass"}, @@ -487,7 +488,7 @@ func TestPagerdutyNotifier(t *testing.T) { Name: "someRule", Message: "someMessage", State: models.AlertStateAlerting, - AlertRuleTags: []*models.Tag{ + AlertRuleTags: []*tag.Tag{ {Key: "keyOnly"}, {Key: "group", Value: "aGroup"}, {Key: "class", Value: "aClass"}, diff --git a/pkg/services/alerting/notifiers/victorops_test.go b/pkg/services/alerting/notifiers/victorops_test.go index 676031b03a5..d3655a256d0 100644 --- a/pkg/services/alerting/notifiers/victorops_test.go +++ b/pkg/services/alerting/notifiers/victorops_test.go @@ -11,6 +11,7 @@ import ( "github.com/grafana/grafana/pkg/services/alerting" "github.com/grafana/grafana/pkg/services/annotations/annotationstest" encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service" + "github.com/grafana/grafana/pkg/services/tag" "github.com/grafana/grafana/pkg/services/validations" "github.com/stretchr/testify/require" @@ -90,7 +91,7 @@ func TestVictoropsNotifier(t *testing.T) { Name: "someRule", Message: "someMessage", State: models.AlertStateAlerting, - AlertRuleTags: []*models.Tag{ + AlertRuleTags: []*tag.Tag{ {Key: "keyOnly"}, {Key: "severity", Value: "warning"}, }, @@ -138,7 +139,7 @@ func TestVictoropsNotifier(t *testing.T) { Name: "someRule", Message: "someMessage", State: models.AlertStateOK, - AlertRuleTags: []*models.Tag{ + AlertRuleTags: []*tag.Tag{ {Key: "keyOnly"}, {Key: "severity", Value: "warning"}, }, diff --git a/pkg/services/alerting/rule.go b/pkg/services/alerting/rule.go index 7dd920d2bfa..0096e63f83b 100644 --- a/pkg/services/alerting/rule.go +++ b/pkg/services/alerting/rule.go @@ -11,6 +11,7 @@ import ( "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/tag" ) var unitMultiplier = map[string]int{ @@ -53,7 +54,7 @@ type Rule struct { State models.AlertStateType Conditions []Condition Notifications []string - AlertRuleTags []*models.Tag + AlertRuleTags []*tag.Tag StateChanges int64 } diff --git a/pkg/services/alerting/store.go b/pkg/services/alerting/store.go index 0fbf0eb5971..c4f58eeed14 100644 --- a/pkg/services/alerting/store.go +++ b/pkg/services/alerting/store.go @@ -12,6 +12,7 @@ import ( "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore/db" + "github.com/grafana/grafana/pkg/services/tag" "github.com/grafana/grafana/pkg/setting" ) @@ -33,20 +34,22 @@ type AlertStore interface { } type sqlStore struct { - db db.DB - cache *localcache.CacheService - log *log.ConcreteLogger - cfg *setting.Cfg + db db.DB + cache *localcache.CacheService + log *log.ConcreteLogger + cfg *setting.Cfg + tagService tag.Service } func ProvideAlertStore( db db.DB, - cacheService *localcache.CacheService, cfg *setting.Cfg) AlertStore { + cacheService *localcache.CacheService, cfg *setting.Cfg, tagService tag.Service) AlertStore { return &sqlStore{ - db: db, - cache: cacheService, - log: log.New("alerting.store"), - cfg: cfg, + db: db, + cache: cacheService, + log: log.New("alerting.store"), + cfg: cfg, + tagService: tagService, } } @@ -188,7 +191,7 @@ func (ss *sqlStore) SaveAlerts(ctx context.Context, dashID int64, alerts []*mode return err } - if err := updateAlerts(existingAlerts, alerts, sess, ss.log); err != nil { + if err := ss.UpdateAlerts(ctx, existingAlerts, alerts, sess, ss.log); err != nil { return err } @@ -200,7 +203,7 @@ func (ss *sqlStore) SaveAlerts(ctx context.Context, dashID int64, alerts []*mode }) } -func updateAlerts(existingAlerts []*models.Alert, alerts []*models.Alert, sess *sqlstore.DBSession, log *log.ConcreteLogger) error { +func (ss *sqlStore) UpdateAlerts(ctx context.Context, existingAlerts []*models.Alert, alerts []*models.Alert, sess *sqlstore.DBSession, log *log.ConcreteLogger) error { for _, alert := range alerts { update := false var alertToUpdate *models.Alert @@ -245,7 +248,7 @@ func updateAlerts(existingAlerts []*models.Alert, alerts []*models.Alert, sess * return err } if tags != nil { - tags, err := sqlstore.EnsureTagsExist(sess, tags) + tags, err := ss.tagService.EnsureTagsExist(ctx, tags) if err != nil { return err } diff --git a/pkg/services/alerting/store_test.go b/pkg/services/alerting/store_test.go index f57b35ee656..21364aa9c8a 100644 --- a/pkg/services/alerting/store_test.go +++ b/pkg/services/alerting/store_test.go @@ -13,6 +13,7 @@ import ( "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore/db" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" @@ -46,12 +47,15 @@ func TestIntegrationAlertingDataAccess(t *testing.T) { var items []*models.Alert setup := func(t *testing.T) { + ss := sqlstore.InitTestDB(t) + tagService := tagimpl.ProvideService(ss) cfg := setting.NewCfg() cfg.RBACEnabled = false store = &sqlStore{ - db: sqlstore.InitTestDB(t), - log: log.New(), - cfg: cfg, + db: ss, + log: log.New(), + cfg: cfg, + tagService: tagService, } testDash = insertTestDashboard(t, store.db, "dashboard with alerts", 1, 0, false, "alert") @@ -285,7 +289,8 @@ func TestIntegrationPausingAlerts(t *testing.T) { defer resetTimeNow() t.Run("Given an alert", func(t *testing.T) { - sqlStore := sqlStore{db: sqlstore.InitTestDB(t), log: log.New()} + ss := sqlstore.InitTestDB(t) + sqlStore := sqlStore{db: ss, log: log.New(), tagService: tagimpl.ProvideService(ss)} testDash := insertTestDashboard(t, sqlStore.db, "dashboard with alerts", 1, 0, false, "alert") alert, err := insertTestAlert("Alerting title", "Alerting message", testDash.OrgId, testDash.Id, simplejson.New(), sqlStore) diff --git a/pkg/services/annotations/annotationsimpl/annotations.go b/pkg/services/annotations/annotationsimpl/annotations.go index 8beb61ee7df..8a515d112f4 100644 --- a/pkg/services/annotations/annotationsimpl/annotations.go +++ b/pkg/services/annotations/annotationsimpl/annotations.go @@ -6,6 +6,7 @@ import ( "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/services/annotations" "github.com/grafana/grafana/pkg/services/sqlstore/db" + "github.com/grafana/grafana/pkg/services/tag" "github.com/grafana/grafana/pkg/setting" ) @@ -13,12 +14,13 @@ type RepositoryImpl struct { store store } -func ProvideService(db db.DB, cfg *setting.Cfg) *RepositoryImpl { +func ProvideService(db db.DB, cfg *setting.Cfg, tagService tag.Service) *RepositoryImpl { return &RepositoryImpl{ store: &SQLAnnotationRepo{ - cfg: cfg, - db: db, - log: log.New("annotations"), + cfg: cfg, + db: db, + log: log.New("annotations"), + tagService: tagService, }, } } diff --git a/pkg/services/annotations/annotationsimpl/xorm_store.go b/pkg/services/annotations/annotationsimpl/xorm_store.go index c2e4d21c0f6..e29e608ad80 100644 --- a/pkg/services/annotations/annotationsimpl/xorm_store.go +++ b/pkg/services/annotations/annotationsimpl/xorm_store.go @@ -8,7 +8,6 @@ import ( "strings" "time" - "github.com/davecgh/go-spew/spew" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/models" ac "github.com/grafana/grafana/pkg/services/accesscontrol" @@ -17,6 +16,7 @@ import ( "github.com/grafana/grafana/pkg/services/sqlstore/db" "github.com/grafana/grafana/pkg/services/sqlstore/permissions" "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" + "github.com/grafana/grafana/pkg/services/tag" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" ) @@ -41,30 +41,31 @@ func validateTimeRange(item *annotations.Item) error { } type SQLAnnotationRepo struct { - cfg *setting.Cfg - db db.DB - log log.Logger + cfg *setting.Cfg + db db.DB + log log.Logger + tagService tag.Service } func (r *SQLAnnotationRepo) Add(ctx context.Context, item *annotations.Item) error { - return r.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { - tags := models.ParseTagPairs(item.Tags) - item.Tags = models.JoinTagPairs(tags) - item.Created = timeNow().UnixNano() / int64(time.Millisecond) - item.Updated = item.Created - if item.Epoch == 0 { - item.Epoch = item.Created - } - if err := validateTimeRange(item); err != nil { - return err - } + tags := tag.ParseTagPairs(item.Tags) + item.Tags = tag.JoinTagPairs(tags) + item.Created = timeNow().UnixNano() / int64(time.Millisecond) + item.Updated = item.Created + if item.Epoch == 0 { + item.Epoch = item.Created + } + if err := validateTimeRange(item); err != nil { + return err + } + return r.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { if _, err := sess.Table("annotation").Insert(item); err != nil { return err } if item.Tags != nil { - tags, err := sqlstore.EnsureTagsExist(sess, tags) + tags, err := r.tagService.EnsureTagsExist(ctx, tags) if err != nil { return err } @@ -74,7 +75,6 @@ func (r *SQLAnnotationRepo) Add(ctx context.Context, item *annotations.Item) err } } } - return nil }) } @@ -111,7 +111,7 @@ func (r *SQLAnnotationRepo) Update(ctx context.Context, item *annotations.Item) } if item.Tags != nil { - tags, err := sqlstore.EnsureTagsExist(sess, models.ParseTagPairs(item.Tags)) + tags, err := r.tagService.EnsureTagsExist(ctx, tag.ParseTagPairs(item.Tags)) if err != nil { return err } @@ -205,7 +205,7 @@ func (r *SQLAnnotationRepo) Get(ctx context.Context, query *annotations.ItemQuer if len(query.Tags) > 0 { keyValueFilters := []string{} - tags := models.ParseTagPairs(query.Tags) + tags := tag.ParseTagPairs(query.Tags) for _, tag := range tags { if tag.Value == "" { keyValueFilters = append(keyValueFilters, "(tag."+r.db.GetDialect().Quote("key")+" = ?)") @@ -249,8 +249,6 @@ func (r *SQLAnnotationRepo) Get(ctx context.Context, query *annotations.ItemQuer // order of ORDER BY arguments match the order of a sql index for performance sql.WriteString(" ORDER BY a.org_id, a.epoch_end DESC, a.epoch DESC" + r.db.GetDialect().Limit(query.Limit) + " ) dt on dt.id = annotation.id") - - spew.Dump(">>>> query: ", sql.String()) if err := sess.SQL(sql.String(), params...).Find(&items); err != nil { items = nil return err diff --git a/pkg/services/annotations/annotationsimpl/xorm_store_test.go b/pkg/services/annotations/annotationsimpl/xorm_store_test.go index 1e77a3dfa6c..e3fb8377f22 100644 --- a/pkg/services/annotations/annotationsimpl/xorm_store_test.go +++ b/pkg/services/annotations/annotationsimpl/xorm_store_test.go @@ -7,6 +7,7 @@ import ( "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" @@ -27,7 +28,7 @@ func TestIntegrationAnnotations(t *testing.T) { t.Skip("skipping integration test") } sql := sqlstore.InitTestDB(t) - repo := SQLAnnotationRepo{db: sql, cfg: setting.NewCfg(), log: log.New("annotation.test")} + repo := SQLAnnotationRepo{db: sql, cfg: setting.NewCfg(), log: log.New("annotation.test"), tagService: tagimpl.ProvideService(sql)} testUser := &user.SignedInUser{ OrgID: 1, @@ -52,7 +53,7 @@ func TestIntegrationAnnotations(t *testing.T) { assert.NoError(t, err) }) - dashboardStore := dashboardstore.ProvideDashboardStore(sql, featuremgmt.WithFeatures()) + dashboardStore := dashboardstore.ProvideDashboardStore(sql, featuremgmt.WithFeatures(), tagimpl.ProvideService(sql)) testDashboard1 := models.SaveDashboardCommand{ UserId: 1, @@ -61,7 +62,8 @@ func TestIntegrationAnnotations(t *testing.T) { "title": "Dashboard 1", }), } - dashboard, err := dashboardStore.SaveDashboard(testDashboard1) + + dashboard, err := dashboardStore.SaveDashboard(context.Background(), testDashboard1) require.NoError(t, err) testDashboard2 := models.SaveDashboardCommand{ @@ -71,7 +73,7 @@ func TestIntegrationAnnotations(t *testing.T) { "title": "Dashboard 2", }), } - dashboard2, err := dashboardStore.SaveDashboard(testDashboard2) + dashboard2, err := dashboardStore.SaveDashboard(context.Background(), testDashboard2) require.NoError(t, err) annotation := &annotations.Item{ @@ -96,7 +98,7 @@ func TestIntegrationAnnotations(t *testing.T) { Type: "alert", Epoch: 21, // Should swap epoch & epochEnd EpochEnd: 20, - Tags: []string{"outage", "error", "type:outage", "server:server-1"}, + Tags: []string{"outage", "type:outage", "server:server-1", "error"}, } err = repo.Add(context.Background(), annotation2) require.NoError(t, err) @@ -392,8 +394,8 @@ func TestIntegrationAnnotationListingWithRBAC(t *testing.T) { t.Skip("skipping integration test") } sql := sqlstore.InitTestDB(t, sqlstore.InitTestDBOpt{}) - repo := SQLAnnotationRepo{db: sql, cfg: setting.NewCfg(), log: log.New("annotation.test")} - dashboardStore := dashboardstore.ProvideDashboardStore(sql, featuremgmt.WithFeatures()) + repo := SQLAnnotationRepo{db: sql, cfg: setting.NewCfg(), log: log.New("annotation.test"), tagService: tagimpl.ProvideService(sql)} + dashboardStore := dashboardstore.ProvideDashboardStore(sql, featuremgmt.WithFeatures(), tagimpl.ProvideService(sql)) testDashboard1 := models.SaveDashboardCommand{ UserId: 1, @@ -402,7 +404,7 @@ func TestIntegrationAnnotationListingWithRBAC(t *testing.T) { "title": "Dashboard 1", }), } - dashboard, err := dashboardStore.SaveDashboard(testDashboard1) + dashboard, err := dashboardStore.SaveDashboard(context.Background(), testDashboard1) require.NoError(t, err) dash1UID := dashboard.Uid @@ -413,7 +415,7 @@ func TestIntegrationAnnotationListingWithRBAC(t *testing.T) { "title": "Dashboard 2", }), } - _, err = dashboardStore.SaveDashboard(testDashboard2) + _, err = dashboardStore.SaveDashboard(context.Background(), testDashboard2) require.NoError(t, err) dash1Annotation := &annotations.Item{ diff --git a/pkg/services/dashboards/dashboard.go b/pkg/services/dashboards/dashboard.go index 036a4b3893e..d5aba4a4cb6 100644 --- a/pkg/services/dashboards/dashboard.go +++ b/pkg/services/dashboards/dashboard.go @@ -39,9 +39,9 @@ type PluginService interface { type DashboardProvisioningService interface { DeleteOrphanedProvisionedDashboards(ctx context.Context, cmd *models.DeleteOrphanedProvisionedDashboardsCommand) error DeleteProvisionedDashboard(ctx context.Context, dashboardID int64, orgID int64) error - GetProvisionedDashboardData(name string) ([]*models.DashboardProvisioning, error) - GetProvisionedDashboardDataByDashboardID(dashboardID int64) (*models.DashboardProvisioning, error) - GetProvisionedDashboardDataByDashboardUID(orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) + GetProvisionedDashboardData(ctx context.Context, name string) ([]*models.DashboardProvisioning, error) + GetProvisionedDashboardDataByDashboardID(ctx context.Context, dashboardID int64) (*models.DashboardProvisioning, error) + GetProvisionedDashboardDataByDashboardUID(ctx context.Context, orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) SaveFolderForProvisionedDashboards(context.Context, *SaveDashboardDTO) (*models.Dashboard, error) SaveProvisionedDashboard(ctx context.Context, dto *SaveDashboardDTO, provisioning *models.DashboardProvisioning) (*models.Dashboard, error) UnprovisionDashboard(ctx context.Context, dashboardID int64) error @@ -61,19 +61,19 @@ type Store interface { // GetDashboardsByPluginID retrieves dashboards identified by plugin. GetDashboardsByPluginID(ctx context.Context, query *models.GetDashboardsByPluginIdQuery) error GetDashboardTags(ctx context.Context, query *models.GetDashboardTagsQuery) error - GetProvisionedDashboardData(name string) ([]*models.DashboardProvisioning, error) - GetProvisionedDataByDashboardID(dashboardID int64) (*models.DashboardProvisioning, error) - GetProvisionedDataByDashboardUID(orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) + GetProvisionedDashboardData(ctx context.Context, name string) ([]*models.DashboardProvisioning, error) + GetProvisionedDataByDashboardID(ctx context.Context, dashboardID int64) (*models.DashboardProvisioning, error) + GetProvisionedDataByDashboardUID(ctx context.Context, orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) HasAdminPermissionInDashboardsOrFolders(ctx context.Context, query *models.HasAdminPermissionInDashboardsOrFoldersQuery) error HasEditPermissionInFolders(ctx context.Context, query *models.HasEditPermissionInFoldersQuery) error // SaveAlerts saves dashboard alerts. SaveAlerts(ctx context.Context, dashID int64, alerts []*models.Alert) error - SaveDashboard(cmd models.SaveDashboardCommand) (*models.Dashboard, error) - SaveProvisionedDashboard(cmd models.SaveDashboardCommand, provisioning *models.DashboardProvisioning) (*models.Dashboard, error) + SaveDashboard(ctx context.Context, cmd models.SaveDashboardCommand) (*models.Dashboard, error) + SaveProvisionedDashboard(ctx context.Context, cmd models.SaveDashboardCommand, provisioning *models.DashboardProvisioning) (*models.Dashboard, error) UnprovisionDashboard(ctx context.Context, id int64) error UpdateDashboardACL(ctx context.Context, uid int64, items []*models.DashboardACL) error // ValidateDashboardBeforeSave validates a dashboard before save. - ValidateDashboardBeforeSave(dashboard *models.Dashboard, overwrite bool) (bool, error) + ValidateDashboardBeforeSave(ctx context.Context, dashboard *models.Dashboard, overwrite bool) (bool, error) DeleteACLByUser(context.Context, int64) error FolderStore diff --git a/pkg/services/dashboards/dashboard_provisioning_mock.go b/pkg/services/dashboards/dashboard_provisioning_mock.go index ddfee0257f6..adbbbbfd17f 100644 --- a/pkg/services/dashboards/dashboard_provisioning_mock.go +++ b/pkg/services/dashboards/dashboard_provisioning_mock.go @@ -45,7 +45,7 @@ func (_m *FakeDashboardProvisioning) DeleteProvisionedDashboard(ctx context.Cont } // GetProvisionedDashboardData provides a mock function with given fields: name -func (_m *FakeDashboardProvisioning) GetProvisionedDashboardData(name string) ([]*models.DashboardProvisioning, error) { +func (_m *FakeDashboardProvisioning) GetProvisionedDashboardData(ctx context.Context, name string) ([]*models.DashboardProvisioning, error) { ret := _m.Called(name) var r0 []*models.DashboardProvisioning @@ -68,7 +68,7 @@ func (_m *FakeDashboardProvisioning) GetProvisionedDashboardData(name string) ([ } // GetProvisionedDashboardDataByDashboardID provides a mock function with given fields: dashboardID -func (_m *FakeDashboardProvisioning) GetProvisionedDashboardDataByDashboardID(dashboardID int64) (*models.DashboardProvisioning, error) { +func (_m *FakeDashboardProvisioning) GetProvisionedDashboardDataByDashboardID(ctx context.Context, dashboardID int64) (*models.DashboardProvisioning, error) { ret := _m.Called(dashboardID) var r0 *models.DashboardProvisioning @@ -91,7 +91,7 @@ func (_m *FakeDashboardProvisioning) GetProvisionedDashboardDataByDashboardID(da } // GetProvisionedDashboardDataByDashboardUID provides a mock function with given fields: orgID, dashboardUID -func (_m *FakeDashboardProvisioning) GetProvisionedDashboardDataByDashboardUID(orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) { +func (_m *FakeDashboardProvisioning) GetProvisionedDashboardDataByDashboardUID(ctx context.Context, orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) { ret := _m.Called(orgID, dashboardUID) var r0 *models.DashboardProvisioning diff --git a/pkg/services/dashboards/database/acl_test.go b/pkg/services/dashboards/database/acl_test.go index 81ad636de7e..7ea9172d523 100644 --- a/pkg/services/dashboards/database/acl_test.go +++ b/pkg/services/dashboards/database/acl_test.go @@ -7,6 +7,7 @@ import ( "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/sqlstore" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" "github.com/stretchr/testify/require" ) @@ -22,7 +23,7 @@ func TestIntegrationDashboardACLDataAccess(t *testing.T) { setup := func(t *testing.T) { sqlStore = sqlstore.InitTestDB(t) - dashboardStore = ProvideDashboardStore(sqlStore, testFeatureToggles) + dashboardStore = ProvideDashboardStore(sqlStore, testFeatureToggles, tagimpl.ProvideService(sqlStore)) currentUser = createUser(t, sqlStore, "viewer", "Viewer", false) savedFolder = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, true, "prod", "webapp") childDash = insertTestDashboard(t, dashboardStore, "2 test dash", 1, savedFolder.Id, false, "prod", "webapp") diff --git a/pkg/services/dashboards/database/database.go b/pkg/services/dashboards/database/database.go index 8bf74f54fac..56ed0f0b458 100644 --- a/pkg/services/dashboards/database/database.go +++ b/pkg/services/dashboards/database/database.go @@ -20,30 +20,32 @@ import ( "github.com/grafana/grafana/pkg/services/sqlstore/permissions" "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" "github.com/grafana/grafana/pkg/services/store" + "github.com/grafana/grafana/pkg/services/tag" "github.com/grafana/grafana/pkg/util" ) type DashboardStore struct { - sqlStore *sqlstore.SQLStore - log log.Logger - dialect migrator.Dialect - features featuremgmt.FeatureToggles + sqlStore *sqlstore.SQLStore + log log.Logger + dialect migrator.Dialect + features featuremgmt.FeatureToggles + tagService tag.Service } // DashboardStore implements the Store interface var _ dashboards.Store = (*DashboardStore)(nil) -func ProvideDashboardStore(sqlStore *sqlstore.SQLStore, features featuremgmt.FeatureToggles) *DashboardStore { - return &DashboardStore{sqlStore: sqlStore, log: log.New("dashboard-store"), dialect: sqlStore.Dialect, features: features} +func ProvideDashboardStore(sqlStore *sqlstore.SQLStore, features featuremgmt.FeatureToggles, tagService tag.Service) *DashboardStore { + return &DashboardStore{sqlStore: sqlStore, log: log.New("dashboard-store"), dialect: sqlStore.Dialect, features: features, tagService: tagService} } func (d *DashboardStore) emitEntityEvent() bool { return d.features != nil && d.features.IsEnabled(featuremgmt.FlagPanelTitleSearch) } -func (d *DashboardStore) ValidateDashboardBeforeSave(dashboard *models.Dashboard, overwrite bool) (bool, error) { +func (d *DashboardStore) ValidateDashboardBeforeSave(ctx context.Context, dashboard *models.Dashboard, overwrite bool) (bool, error) { isParentFolderChanged := false - err := d.sqlStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { var err error isParentFolderChanged, err = getExistingDashboardByIdOrUidForUpdate(sess, dashboard, d.sqlStore.Dialect, overwrite) if err != nil { @@ -132,9 +134,9 @@ func (d *DashboardStore) GetFolderByUID(ctx context.Context, orgID int64, uid st return models.DashboardToFolder(&dashboard), nil } -func (d *DashboardStore) GetProvisionedDataByDashboardID(dashboardID int64) (*models.DashboardProvisioning, error) { +func (d *DashboardStore) GetProvisionedDataByDashboardID(ctx context.Context, dashboardID int64) (*models.DashboardProvisioning, error) { var data models.DashboardProvisioning - err := d.sqlStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { _, err := sess.Where("dashboard_id = ?", dashboardID).Get(&data) return err }) @@ -145,9 +147,9 @@ func (d *DashboardStore) GetProvisionedDataByDashboardID(dashboardID int64) (*mo return &data, err } -func (d *DashboardStore) GetProvisionedDataByDashboardUID(orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) { +func (d *DashboardStore) GetProvisionedDataByDashboardUID(ctx context.Context, orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) { var provisionedDashboard models.DashboardProvisioning - err := d.sqlStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { var dashboard models.Dashboard exists, err := sess.Where("org_id = ? AND uid = ?", orgID, dashboardUID).Get(&dashboard) if err != nil { @@ -168,16 +170,16 @@ func (d *DashboardStore) GetProvisionedDataByDashboardUID(orgID int64, dashboard return &provisionedDashboard, err } -func (d *DashboardStore) GetProvisionedDashboardData(name string) ([]*models.DashboardProvisioning, error) { +func (d *DashboardStore) GetProvisionedDashboardData(ctx context.Context, name string) ([]*models.DashboardProvisioning, error) { var result []*models.DashboardProvisioning - err := d.sqlStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { return sess.Where("name = ?", name).Find(&result) }) return result, err } -func (d *DashboardStore) SaveProvisionedDashboard(cmd models.SaveDashboardCommand, provisioning *models.DashboardProvisioning) (*models.Dashboard, error) { - err := d.sqlStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error { +func (d *DashboardStore) SaveProvisionedDashboard(ctx context.Context, cmd models.SaveDashboardCommand, provisioning *models.DashboardProvisioning) (*models.Dashboard, error) { + err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { if err := saveDashboard(sess, &cmd, d.emitEntityEvent()); err != nil { return err } @@ -192,8 +194,8 @@ func (d *DashboardStore) SaveProvisionedDashboard(cmd models.SaveDashboardComman return cmd.Result, err } -func (d *DashboardStore) SaveDashboard(cmd models.SaveDashboardCommand) (*models.Dashboard, error) { - err := d.sqlStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error { +func (d *DashboardStore) SaveDashboard(ctx context.Context, cmd models.SaveDashboardCommand) (*models.Dashboard, error) { + err := d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { return saveDashboard(sess, &cmd, d.emitEntityEvent()) }) return cmd.Result, err @@ -230,13 +232,13 @@ func (d *DashboardStore) UpdateDashboardACL(ctx context.Context, dashboardID int } func (d *DashboardStore) SaveAlerts(ctx context.Context, dashID int64, alerts []*models.Alert) error { - return d.sqlStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + return d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { existingAlerts, err := GetAlertsByDashboardId2(dashID, sess) if err != nil { return err } - if err := updateAlerts(existingAlerts, alerts, sess, d.log); err != nil { + if err := d.updateAlerts(ctx, existingAlerts, alerts, d.log); err != nil { return err } @@ -571,64 +573,65 @@ func GetAlertsByDashboardId2(dashboardId int64, sess *sqlstore.DBSession) ([]*mo return alerts, nil } -func updateAlerts(existingAlerts []*models.Alert, alerts []*models.Alert, sess *sqlstore.DBSession, log log.Logger) error { - for _, alert := range alerts { - update := false - var alertToUpdate *models.Alert +func (d *DashboardStore) updateAlerts(ctx context.Context, existingAlerts []*models.Alert, alerts []*models.Alert, log log.Logger) error { + return d.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { + for _, alert := range alerts { + update := false + var alertToUpdate *models.Alert - for _, k := range existingAlerts { - if alert.PanelId == k.PanelId { - update = true - alert.Id = k.Id - alertToUpdate = k - break + for _, k := range existingAlerts { + if alert.PanelId == k.PanelId { + update = true + alert.Id = k.Id + alertToUpdate = k + break + } } - } - if update { - if alertToUpdate.ContainsUpdates(alert) { + if update { + if alertToUpdate.ContainsUpdates(alert) { + alert.Updated = time.Now() + alert.State = alertToUpdate.State + sess.MustCols("message", "for") + + _, err := sess.ID(alert.Id).Update(alert) + if err != nil { + return err + } + + log.Debug("Alert updated", "name", alert.Name, "id", alert.Id) + } + } else { alert.Updated = time.Now() - alert.State = alertToUpdate.State - sess.MustCols("message", "for") + alert.Created = time.Now() + alert.State = models.AlertStateUnknown + alert.NewStateDate = time.Now() - _, err := sess.ID(alert.Id).Update(alert) + _, err := sess.Insert(alert) if err != nil { return err } - log.Debug("Alert updated", "name", alert.Name, "id", alert.Id) + log.Debug("Alert inserted", "name", alert.Name, "id", alert.Id) } - } else { - alert.Updated = time.Now() - alert.Created = time.Now() - alert.State = models.AlertStateUnknown - alert.NewStateDate = time.Now() - - _, err := sess.Insert(alert) - if err != nil { + tags := alert.GetTagsFromSettings() + if _, err := sess.Exec("DELETE FROM alert_rule_tag WHERE alert_id = ?", alert.Id); err != nil { return err } - - log.Debug("Alert inserted", "name", alert.Name, "id", alert.Id) - } - tags := alert.GetTagsFromSettings() - if _, err := sess.Exec("DELETE FROM alert_rule_tag WHERE alert_id = ?", alert.Id); err != nil { - return err - } - if tags != nil { - tags, err := EnsureTagsExist(sess, tags) - if err != nil { - return err - } - for _, tag := range tags { - if _, err := sess.Exec("INSERT INTO alert_rule_tag (alert_id, tag_id) VALUES(?,?)", alert.Id, tag.Id); err != nil { + if tags != nil { + tags, err := d.tagService.EnsureTagsExist(ctx, tags) + if err != nil { return err } + for _, tag := range tags { + if _, err := sess.Exec("INSERT INTO alert_rule_tag (alert_id, tag_id) VALUES(?,?)", alert.Id, tag.Id); err != nil { + return err + } + } } } - } - - return nil + return nil + }) } func (d *DashboardStore) deleteMissingAlerts(alerts []*models.Alert, existingAlerts []*models.Alert, sess *sqlstore.DBSession) error { @@ -676,28 +679,6 @@ func (d *DashboardStore) deleteAlertByIdInternal(alertId int64, reason string, s return nil } -func EnsureTagsExist(sess *sqlstore.DBSession, tags []*models.Tag) ([]*models.Tag, error) { - for _, tag := range tags { - var existingTag models.Tag - - // check if it exists - exists, err := sess.Table("tag").Where("`key`=? AND `value`=?", tag.Key, tag.Value).Get(&existingTag) - if err != nil { - return nil, err - } - if exists { - tag.Id = existingTag.Id - } else { - _, err := sess.Table("tag").Insert(tag) - if err != nil { - return nil, err - } - } - } - - return tags, nil -} - func (d *DashboardStore) GetDashboardsByPluginID(ctx context.Context, query *models.GetDashboardsByPluginIdQuery) error { return d.sqlStore.WithDbSession(ctx, func(dbSession *sqlstore.DBSession) error { var dashboards = make([]*models.Dashboard, 0) diff --git a/pkg/services/dashboards/database/database_folder_test.go b/pkg/services/dashboards/database/database_folder_test.go index d07d8fcd46e..03459fcac63 100644 --- a/pkg/services/dashboards/database/database_folder_test.go +++ b/pkg/services/dashboards/database/database_folder_test.go @@ -12,6 +12,7 @@ import ( "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/sqlstore" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" ) @@ -30,7 +31,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { setup := func() { sqlStore = sqlstore.InitTestDB(t) sqlStore.Cfg.RBACEnabled = false - dashboardStore = ProvideDashboardStore(sqlStore, testFeatureToggles) + dashboardStore = ProvideDashboardStore(sqlStore, testFeatureToggles, tagimpl.ProvideService(sqlStore)) folder = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, true, "prod", "webapp") dashInRoot = insertTestDashboard(t, dashboardStore, "test dash 67", 1, 0, false, "prod", "webapp") childDash = insertTestDashboard(t, dashboardStore, "test dash 23", 1, folder.Id, false, "prod", "webapp") @@ -183,7 +184,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { setup2 := func() { sqlStore = sqlstore.InitTestDB(t) - dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles) + dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles, tagimpl.ProvideService(sqlStore)) folder1 = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, true, "prod") folder2 = insertTestDashboard(t, dashboardStore, "2 test dash folder", 1, 0, true, "prod") dashInRoot = insertTestDashboard(t, dashboardStore, "test dash 67", 1, 0, false, "prod") @@ -288,7 +289,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { setup3 := func() { sqlStore = sqlstore.InitTestDB(t) - dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles) + dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles, tagimpl.ProvideService(sqlStore)) folder1 = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, true, "prod") folder2 = insertTestDashboard(t, dashboardStore, "2 test dash folder", 1, 0, true, "prod") insertTestDashboard(t, dashboardStore, "folder in another org", 2, 0, true, "prod") @@ -470,7 +471,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { var sqlStore *sqlstore.SQLStore var folder1, folder2 *models.Dashboard sqlStore = sqlstore.InitTestDB(t) - dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles) + dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles, tagimpl.ProvideService(sqlStore)) folder2 = insertTestDashboard(t, dashboardStore, "TEST", orgId, 0, true, "prod") _ = insertTestDashboard(t, dashboardStore, title, orgId, folder2.Id, false, "prod") folder1 = insertTestDashboard(t, dashboardStore, title, orgId, 0, true, "prod") @@ -485,7 +486,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { t.Run("GetFolderByUID", func(t *testing.T) { var orgId int64 = 1 sqlStore := sqlstore.InitTestDB(t) - dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles) + dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles, tagimpl.ProvideService(sqlStore)) folder := insertTestDashboard(t, dashboardStore, "TEST", orgId, 0, true, "prod") dash := insertTestDashboard(t, dashboardStore, "Very Unique Name", orgId, folder.Id, false, "prod") @@ -509,7 +510,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { t.Run("GetFolderByID", func(t *testing.T) { var orgId int64 = 1 sqlStore := sqlstore.InitTestDB(t) - dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles) + dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles, tagimpl.ProvideService(sqlStore)) folder := insertTestDashboard(t, dashboardStore, "TEST", orgId, 0, true, "prod") dash := insertTestDashboard(t, dashboardStore, "Very Unique Name", orgId, folder.Id, false, "prod") @@ -542,7 +543,7 @@ func moveDashboard(t *testing.T, dashboardStore *DashboardStore, orgId int64, da Dashboard: dashboard, Overwrite: true, } - dash, err := dashboardStore.SaveDashboard(cmd) + dash, err := dashboardStore.SaveDashboard(context.Background(), cmd) require.NoError(t, err) return dash diff --git a/pkg/services/dashboards/database/database_provisioning_test.go b/pkg/services/dashboards/database/database_provisioning_test.go index fdd71876782..cd87e2732a9 100644 --- a/pkg/services/dashboards/database/database_provisioning_test.go +++ b/pkg/services/dashboards/database/database_provisioning_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/grafana/grafana/pkg/services/sqlstore" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/models" @@ -18,7 +19,7 @@ func TestIntegrationDashboardProvisioningTest(t *testing.T) { t.Skip("skipping integration test") } sqlStore := sqlstore.InitTestDB(t) - dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles) + dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles, tagimpl.ProvideService(sqlStore)) folderCmd := models.SaveDashboardCommand{ OrgId: 1, @@ -30,7 +31,7 @@ func TestIntegrationDashboardProvisioningTest(t *testing.T) { }), } - dash, err := dashboardStore.SaveDashboard(folderCmd) + dash, err := dashboardStore.SaveDashboard(context.Background(), folderCmd) require.Nil(t, err) saveDashboardCmd := models.SaveDashboardCommand{ @@ -52,7 +53,7 @@ func TestIntegrationDashboardProvisioningTest(t *testing.T) { Updated: now.Unix(), } - dash, err := dashboardStore.SaveProvisionedDashboard(saveDashboardCmd, provisioning) + dash, err := dashboardStore.SaveProvisionedDashboard(context.Background(), saveDashboardCmd, provisioning) require.Nil(t, err) require.NotNil(t, dash) require.NotEqual(t, 0, dash.Id) @@ -74,7 +75,7 @@ func TestIntegrationDashboardProvisioningTest(t *testing.T) { Updated: now.Unix(), } - anotherDash, err := dashboardStore.SaveProvisionedDashboard(saveCmd, provisioning) + anotherDash, err := dashboardStore.SaveProvisionedDashboard(context.Background(), saveCmd, provisioning) require.Nil(t, err) query := &models.GetDashboardsQuery{DashboardIds: []int64{anotherDash.Id}} @@ -94,7 +95,7 @@ func TestIntegrationDashboardProvisioningTest(t *testing.T) { }) t.Run("Can query for provisioned dashboards", func(t *testing.T) { - rslt, err := dashboardStore.GetProvisionedDashboardData("default") + rslt, err := dashboardStore.GetProvisionedDashboardData(context.Background(), "default") require.Nil(t, err) require.Equal(t, 1, len(rslt)) @@ -103,13 +104,13 @@ func TestIntegrationDashboardProvisioningTest(t *testing.T) { }) t.Run("Can query for one provisioned dashboard", func(t *testing.T) { - data, err := dashboardStore.GetProvisionedDataByDashboardID(dash.Id) + data, err := dashboardStore.GetProvisionedDataByDashboardID(context.Background(), dash.Id) require.Nil(t, err) require.NotNil(t, data) }) t.Run("Can query for none provisioned dashboard", func(t *testing.T) { - data, err := dashboardStore.GetProvisionedDataByDashboardID(3000) + data, err := dashboardStore.GetProvisionedDataByDashboardID(context.Background(), 3000) require.Nil(t, err) require.Nil(t, data) }) @@ -122,7 +123,7 @@ func TestIntegrationDashboardProvisioningTest(t *testing.T) { require.Nil(t, dashboardStore.DeleteDashboard(context.Background(), deleteCmd)) - data, err := dashboardStore.GetProvisionedDataByDashboardID(dash.Id) + data, err := dashboardStore.GetProvisionedDataByDashboardID(context.Background(), dash.Id) require.Nil(t, err) require.Nil(t, data) }) @@ -130,7 +131,7 @@ func TestIntegrationDashboardProvisioningTest(t *testing.T) { t.Run("UnprovisionDashboard should delete provisioning metadata", func(t *testing.T) { require.Nil(t, dashboardStore.UnprovisionDashboard(context.Background(), dashId)) - data, err := dashboardStore.GetProvisionedDataByDashboardID(dashId) + data, err := dashboardStore.GetProvisionedDataByDashboardID(context.Background(), dashId) require.Nil(t, err) require.Nil(t, data) }) diff --git a/pkg/services/dashboards/database/database_test.go b/pkg/services/dashboards/database/database_test.go index 5a34a571d67..7d723498363 100644 --- a/pkg/services/dashboards/database/database_test.go +++ b/pkg/services/dashboards/database/database_test.go @@ -19,6 +19,7 @@ import ( "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" "github.com/grafana/grafana/pkg/services/star" "github.com/grafana/grafana/pkg/services/star/starimpl" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" ) @@ -34,7 +35,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) { setup := func() { sqlStore = sqlstore.InitTestDB(t) starService = starimpl.ProvideService(sqlStore, sqlStore.Cfg) - dashboardStore = ProvideDashboardStore(sqlStore, testFeatureToggles) + dashboardStore = ProvideDashboardStore(sqlStore, testFeatureToggles, tagimpl.ProvideService(sqlStore)) savedFolder = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, true, "prod", "webapp") savedDash = insertTestDashboard(t, dashboardStore, "test dash 23", 1, savedFolder.Id, false, "prod", "webapp") insertTestDashboard(t, dashboardStore, "test dash 45", 1, savedFolder.Id, false, "prod") @@ -162,7 +163,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) { }), UserId: 100, } - dashboard, err := dashboardStore.SaveDashboard(cmd) + dashboard, err := dashboardStore.SaveDashboard(context.Background(), cmd) require.NoError(t, err) require.EqualValues(t, dashboard.CreatedBy, 100) require.False(t, dashboard.Created.IsZero()) @@ -183,7 +184,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) { FolderId: 2, UserId: 100, } - dash, err := dashboardStore.SaveDashboard(cmd) + dash, err := dashboardStore.SaveDashboard(context.Background(), cmd) require.NoError(t, err) require.EqualValues(t, dash.FolderId, 2) @@ -198,7 +199,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) { Overwrite: true, UserId: 100, } - _, err = dashboardStore.SaveDashboard(cmd) + _, err = dashboardStore.SaveDashboard(context.Background(), cmd) require.NoError(t, err) query := models.GetDashboardQuery{ @@ -274,7 +275,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) { }), } - _, err := dashboardStore.SaveDashboard(cmd) + _, err := dashboardStore.SaveDashboard(context.Background(), cmd) require.Equal(t, err, dashboards.ErrDashboardNotFound) }) @@ -288,7 +289,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) { "tags": []interface{}{}, }), } - _, err := dashboardStore.SaveDashboard(cmd) + _, err := dashboardStore.SaveDashboard(context.Background(), cmd) require.NoError(t, err) }) @@ -485,7 +486,7 @@ func TestIntegrationDashboardDataAccessGivenPluginWithImportedDashboards(t *test t.Skip("skipping integration test") } sqlStore := sqlstore.InitTestDB(t) - dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles) + dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles, tagimpl.ProvideService(sqlStore)) pluginId := "test-app" appFolder := insertTestDashboardForPlugin(t, dashboardStore, "app-test", 1, 0, true, pluginId) @@ -507,7 +508,7 @@ func TestIntegrationDashboard_SortingOptions(t *testing.T) { t.Skip("skipping integration test") } sqlStore := sqlstore.InitTestDB(t) - dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles) + dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles, tagimpl.ProvideService(sqlStore)) dashB := insertTestDashboard(t, dashboardStore, "Beta", 1, 0, false) dashA := insertTestDashboard(t, dashboardStore, "Alfa", 1, 0, false) @@ -556,7 +557,7 @@ func TestIntegrationDashboard_Filter(t *testing.T) { t.Skip("skipping integration test") } sqlStore := sqlstore.InitTestDB(t) - dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles) + dashboardStore := ProvideDashboardStore(sqlStore, testFeatureToggles, tagimpl.ProvideService(sqlStore)) insertTestDashboard(t, dashboardStore, "Alfa", 1, 0, false) dashB := insertTestDashboard(t, dashboardStore, "Beta", 1, 0, false) qNoFilter := &models.FindPersistedDashboardsQuery{ @@ -696,7 +697,7 @@ func insertTestDashboard(t *testing.T, dashboardStore *DashboardStore, title str "tags": tags, }), } - dash, err := dashboardStore.SaveDashboard(cmd) + dash, err := dashboardStore.SaveDashboard(context.Background(), cmd) require.NoError(t, err) require.NotNil(t, dash) dash.Data.Set("id", dash.Id) @@ -718,7 +719,7 @@ func insertTestDashboardForPlugin(t *testing.T, dashboardStore *DashboardStore, PluginId: pluginId, } - dash, err := dashboardStore.SaveDashboard(cmd) + dash, err := dashboardStore.SaveDashboard(context.Background(), cmd) require.NoError(t, err) return dash diff --git a/pkg/services/dashboards/service/dashboard_service.go b/pkg/services/dashboards/service/dashboard_service.go index 4c095b99e0d..b74ba9b7d26 100644 --- a/pkg/services/dashboards/service/dashboard_service.go +++ b/pkg/services/dashboards/service/dashboard_service.go @@ -62,16 +62,16 @@ func ProvideDashboardService( } } -func (dr *DashboardServiceImpl) GetProvisionedDashboardData(name string) ([]*models.DashboardProvisioning, error) { - return dr.dashboardStore.GetProvisionedDashboardData(name) +func (dr *DashboardServiceImpl) GetProvisionedDashboardData(ctx context.Context, name string) ([]*models.DashboardProvisioning, error) { + return dr.dashboardStore.GetProvisionedDashboardData(ctx, name) } -func (dr *DashboardServiceImpl) GetProvisionedDashboardDataByDashboardID(dashboardID int64) (*models.DashboardProvisioning, error) { - return dr.dashboardStore.GetProvisionedDataByDashboardID(dashboardID) +func (dr *DashboardServiceImpl) GetProvisionedDashboardDataByDashboardID(ctx context.Context, dashboardID int64) (*models.DashboardProvisioning, error) { + return dr.dashboardStore.GetProvisionedDataByDashboardID(ctx, dashboardID) } -func (dr *DashboardServiceImpl) GetProvisionedDashboardDataByDashboardUID(orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) { - return dr.dashboardStore.GetProvisionedDataByDashboardUID(orgID, dashboardUID) +func (dr *DashboardServiceImpl) GetProvisionedDashboardDataByDashboardUID(ctx context.Context, orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) { + return dr.dashboardStore.GetProvisionedDataByDashboardUID(ctx, orgID, dashboardUID) } func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, dto *dashboards.SaveDashboardDTO, shouldValidateAlerts bool, @@ -112,7 +112,7 @@ func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, d } } - isParentFolderChanged, err := dr.dashboardStore.ValidateDashboardBeforeSave(dash, dto.Overwrite) + isParentFolderChanged, err := dr.dashboardStore.ValidateDashboardBeforeSave(ctx, dash, dto.Overwrite) if err != nil { return nil, err } @@ -129,7 +129,7 @@ func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, d } if validateProvisionedDashboard { - provisionedData, err := dr.GetProvisionedDashboardDataByDashboardID(dash.Id) + provisionedData, err := dr.GetProvisionedDashboardDataByDashboardID(ctx, dash.Id) if err != nil { return nil, err } @@ -225,7 +225,7 @@ func (dr *DashboardServiceImpl) SaveProvisionedDashboard(ctx context.Context, dt } // dashboard - dash, err := dr.dashboardStore.SaveProvisionedDashboard(*cmd, provisioning) + dash, err := dr.dashboardStore.SaveProvisionedDashboard(ctx, *cmd, provisioning) if err != nil { return nil, err } @@ -266,7 +266,7 @@ func (dr *DashboardServiceImpl) SaveFolderForProvisionedDashboards(ctx context.C return nil, err } - dash, err := dr.dashboardStore.SaveDashboard(*cmd) + dash, err := dr.dashboardStore.SaveDashboard(ctx, *cmd) if err != nil { return nil, err } @@ -313,7 +313,7 @@ func (dr *DashboardServiceImpl) SaveDashboard(ctx context.Context, dto *dashboar return nil, err } - dash, err := dr.dashboardStore.SaveDashboard(*cmd) + dash, err := dr.dashboardStore.SaveDashboard(ctx, *cmd) if err != nil { return nil, fmt.Errorf("saving dashboard failed: %w", err) } @@ -407,7 +407,7 @@ func (dr *DashboardServiceImpl) DeleteProvisionedDashboard(ctx context.Context, func (dr *DashboardServiceImpl) deleteDashboard(ctx context.Context, dashboardId int64, orgId int64, validateProvisionedDashboard bool) error { if validateProvisionedDashboard { - provisionedData, err := dr.GetProvisionedDashboardDataByDashboardID(dashboardId) + provisionedData, err := dr.GetProvisionedDashboardDataByDashboardID(ctx, dashboardId) if err != nil { return fmt.Errorf("%v: %w", "failed to check if dashboard is provisioned", err) } @@ -434,7 +434,7 @@ func (dr *DashboardServiceImpl) ImportDashboard(ctx context.Context, dto *dashbo return nil, err } - dash, err := dr.dashboardStore.SaveDashboard(*cmd) + dash, err := dr.dashboardStore.SaveDashboard(ctx, *cmd) if err != nil { return nil, err } diff --git a/pkg/services/dashboards/service/dashboard_service_integration_test.go b/pkg/services/dashboards/service/dashboard_service_integration_test.go index 33ee9be9362..9e72a7b5f39 100644 --- a/pkg/services/dashboards/service/dashboard_service_integration_test.go +++ b/pkg/services/dashboards/service/dashboard_service_integration_test.go @@ -17,6 +17,7 @@ import ( "github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/sqlstore" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/team/teamtest" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" @@ -819,7 +820,7 @@ func permissionScenario(t *testing.T, desc string, canSave bool, fn permissionSc cfg := setting.NewCfg() cfg.RBACEnabled = false sqlStore := sqlstore.InitTestDB(t) - dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) service := ProvideDashboardService( cfg, dashboardStore, &dummyDashAlertExtractor{}, featuremgmt.WithFeatures(), @@ -873,7 +874,7 @@ func callSaveWithResult(t *testing.T, cmd models.SaveDashboardCommand, sqlStore t.Helper() dto := toSaveDashboardDto(cmd) - dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) cfg := setting.NewCfg() cfg.RBACEnabled = false cfg.IsFeatureToggleEnabled = featuremgmt.WithFeatures().IsEnabled @@ -892,7 +893,7 @@ func callSaveWithResult(t *testing.T, cmd models.SaveDashboardCommand, sqlStore func callSaveWithError(cmd models.SaveDashboardCommand, sqlStore *sqlstore.SQLStore) error { dto := toSaveDashboardDto(cmd) - dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) cfg := setting.NewCfg() cfg.RBACEnabled = false cfg.IsFeatureToggleEnabled = featuremgmt.WithFeatures().IsEnabled @@ -929,7 +930,7 @@ func saveTestDashboard(t *testing.T, title string, orgID, folderID int64, sqlSto }, } - dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) cfg := setting.NewCfg() cfg.RBACEnabled = false cfg.IsFeatureToggleEnabled = featuremgmt.WithFeatures().IsEnabled @@ -967,7 +968,7 @@ func saveTestFolder(t *testing.T, title string, orgID int64, sqlStore *sqlstore. }, } - dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) cfg := setting.NewCfg() cfg.RBACEnabled = false cfg.IsFeatureToggleEnabled = featuremgmt.WithFeatures().IsEnabled diff --git a/pkg/services/dashboards/service/folder_service.go b/pkg/services/dashboards/service/folder_service.go index 90127fb0567..96367181242 100644 --- a/pkg/services/dashboards/service/folder_service.go +++ b/pkg/services/dashboards/service/folder_service.go @@ -164,7 +164,7 @@ func (f *FolderServiceImpl) CreateFolder(ctx context.Context, user *user.SignedI return nil, toFolderError(err) } - dash, err := f.dashboardStore.SaveDashboard(*saveDashboardCmd) + dash, err := f.dashboardStore.SaveDashboard(ctx, *saveDashboardCmd) if err != nil { return nil, toFolderError(err) } @@ -228,7 +228,7 @@ func (f *FolderServiceImpl) UpdateFolder(ctx context.Context, user *user.SignedI return toFolderError(err) } - dash, err := f.dashboardStore.SaveDashboard(*saveDashboardCmd) + dash, err := f.dashboardStore.SaveDashboard(ctx, *saveDashboardCmd) if err != nil { return toFolderError(err) } diff --git a/pkg/services/dashboards/store_mock.go b/pkg/services/dashboards/store_mock.go index 4e506704aa9..cd30c34a745 100644 --- a/pkg/services/dashboards/store_mock.go +++ b/pkg/services/dashboards/store_mock.go @@ -231,7 +231,7 @@ func (_m *FakeDashboardStore) GetFolderByUID(ctx context.Context, orgID int64, u } // GetProvisionedDashboardData provides a mock function with given fields: name -func (_m *FakeDashboardStore) GetProvisionedDashboardData(name string) ([]*models.DashboardProvisioning, error) { +func (_m *FakeDashboardStore) GetProvisionedDashboardData(ctx context.Context, name string) ([]*models.DashboardProvisioning, error) { ret := _m.Called(name) var r0 []*models.DashboardProvisioning @@ -254,7 +254,7 @@ func (_m *FakeDashboardStore) GetProvisionedDashboardData(name string) ([]*model } // GetProvisionedDataByDashboardID provides a mock function with given fields: dashboardID -func (_m *FakeDashboardStore) GetProvisionedDataByDashboardID(dashboardID int64) (*models.DashboardProvisioning, error) { +func (_m *FakeDashboardStore) GetProvisionedDataByDashboardID(ctx context.Context, dashboardID int64) (*models.DashboardProvisioning, error) { ret := _m.Called(dashboardID) var r0 *models.DashboardProvisioning @@ -277,7 +277,7 @@ func (_m *FakeDashboardStore) GetProvisionedDataByDashboardID(dashboardID int64) } // GetProvisionedDataByDashboardUID provides a mock function with given fields: orgID, dashboardUID -func (_m *FakeDashboardStore) GetProvisionedDataByDashboardUID(orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) { +func (_m *FakeDashboardStore) GetProvisionedDataByDashboardUID(ctx context.Context, orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) { ret := _m.Called(orgID, dashboardUID) var r0 *models.DashboardProvisioning @@ -342,7 +342,7 @@ func (_m *FakeDashboardStore) SaveAlerts(ctx context.Context, dashID int64, aler } // SaveDashboard provides a mock function with given fields: cmd -func (_m *FakeDashboardStore) SaveDashboard(cmd models.SaveDashboardCommand) (*models.Dashboard, error) { +func (_m *FakeDashboardStore) SaveDashboard(ctx context.Context, cmd models.SaveDashboardCommand) (*models.Dashboard, error) { ret := _m.Called(cmd) var r0 *models.Dashboard @@ -365,7 +365,7 @@ func (_m *FakeDashboardStore) SaveDashboard(cmd models.SaveDashboardCommand) (*m } // SaveProvisionedDashboard provides a mock function with given fields: cmd, provisioning -func (_m *FakeDashboardStore) SaveProvisionedDashboard(cmd models.SaveDashboardCommand, provisioning *models.DashboardProvisioning) (*models.Dashboard, error) { +func (_m *FakeDashboardStore) SaveProvisionedDashboard(ctx context.Context, cmd models.SaveDashboardCommand, provisioning *models.DashboardProvisioning) (*models.Dashboard, error) { ret := _m.Called(cmd, provisioning) var r0 *models.Dashboard @@ -416,7 +416,7 @@ func (_m *FakeDashboardStore) UpdateDashboardACL(ctx context.Context, uid int64, } // ValidateDashboardBeforeSave provides a mock function with given fields: dashboard, overwrite -func (_m *FakeDashboardStore) ValidateDashboardBeforeSave(dashboard *models.Dashboard, overwrite bool) (bool, error) { +func (_m *FakeDashboardStore) ValidateDashboardBeforeSave(ctx context.Context, dashboard *models.Dashboard, overwrite bool) (bool, error) { ret := _m.Called(dashboard, overwrite) var r0 bool diff --git a/pkg/services/guardian/accesscontrol_guardian_test.go b/pkg/services/guardian/accesscontrol_guardian_test.go index e97178993f9..406c372d4fc 100644 --- a/pkg/services/guardian/accesscontrol_guardian_test.go +++ b/pkg/services/guardian/accesscontrol_guardian_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" "github.com/stretchr/testify/assert" @@ -589,8 +590,8 @@ func setupAccessControlGuardianTest(t *testing.T, uid string, permissions []acce toSave.SetUid(uid) // seed dashboard - dashStore := dashdb.ProvideDashboardStore(store, featuremgmt.WithFeatures()) - dash, err := dashStore.SaveDashboard(models.SaveDashboardCommand{ + dashStore := dashdb.ProvideDashboardStore(store, featuremgmt.WithFeatures(), tagimpl.ProvideService(store)) + dash, err := dashStore.SaveDashboard(context.Background(), models.SaveDashboardCommand{ Dashboard: toSave.Data, UserId: 1, OrgId: 1, diff --git a/pkg/services/libraryelements/libraryelements_test.go b/pkg/services/libraryelements/libraryelements_test.go index 512ba461d33..28199050485 100644 --- a/pkg/services/libraryelements/libraryelements_test.go +++ b/pkg/services/libraryelements/libraryelements_test.go @@ -26,6 +26,7 @@ import ( "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore/mockstore" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/team/teamtest" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" @@ -271,7 +272,7 @@ func createDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, user user.Signed Overwrite: false, } - dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) dashAlertExtractor := alerting.ProvideDashAlertExtractorService(nil, nil, nil) features := featuremgmt.WithFeatures() cfg := setting.NewCfg() @@ -301,7 +302,7 @@ func createFolderWithACL(t *testing.T, sqlStore *sqlstore.SQLStore, title string ac := acmock.New() folderPermissions := acmock.NewMockedPermissionsService() dashboardPermissions := acmock.NewMockedPermissionsService() - dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) d := dashboardservice.ProvideDashboardService( cfg, dashboardStore, nil, @@ -405,7 +406,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo orgID := int64(1) role := org.RoleAdmin sqlStore := sqlstore.InitTestDB(t) - dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) features := featuremgmt.WithFeatures() ac := acmock.New().WithDisabled() // TODO: Update tests to work with rbac diff --git a/pkg/services/librarypanels/librarypanels_test.go b/pkg/services/librarypanels/librarypanels_test.go index b343220bd72..7350969bdb9 100644 --- a/pkg/services/librarypanels/librarypanels_test.go +++ b/pkg/services/librarypanels/librarypanels_test.go @@ -24,6 +24,7 @@ import ( "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore/mockstore" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/team/teamtest" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" @@ -1376,7 +1377,7 @@ func createDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, user *user.Signe Overwrite: false, } - dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) dashAlertService := alerting.ProvideDashAlertExtractorService(nil, nil, nil) cfg := setting.NewCfg() cfg.RBACEnabled = false @@ -1403,7 +1404,7 @@ func createFolderWithACL(t *testing.T, sqlStore *sqlstore.SQLStore, title string features := featuremgmt.WithFeatures() folderPermissions := acmock.NewMockedPermissionsService() dashboardPermissions := acmock.NewMockedPermissionsService() - dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) d := dashboardservice.ProvideDashboardService(cfg, dashboardStore, nil, features, folderPermissions, dashboardPermissions, ac) s := dashboardservice.ProvideFolderService(cfg, d, dashboardStore, nil, features, folderPermissions, ac, busmock.New()) @@ -1496,7 +1497,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo orgID := int64(1) role := org.RoleAdmin sqlStore := sqlstore.InitTestDB(t) - dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := database.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) features := featuremgmt.WithFeatures() ac := acmock.New() diff --git a/pkg/services/ngalert/tests/util.go b/pkg/services/ngalert/tests/util.go index d4bc4ec4897..2fdccddbe5c 100644 --- a/pkg/services/ngalert/tests/util.go +++ b/pkg/services/ngalert/tests/util.go @@ -29,6 +29,7 @@ import ( "github.com/grafana/grafana/pkg/services/secrets/database" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" "github.com/grafana/grafana/pkg/services/sqlstore" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" @@ -61,7 +62,7 @@ func SetupTestEnv(t *testing.T, baseInterval time.Duration) (*ngalert.AlertNG, * m := metrics.NewNGAlert(prometheus.NewRegistry()) sqlStore := sqlstore.InitTestDB(t) secretsService := secretsManager.SetupTestService(t, database.ProvideSecretsStore(sqlStore)) - dashboardStore := databasestore.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := databasestore.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) ac := acmock.New() features := featuremgmt.WithFeatures() diff --git a/pkg/services/provisioning/dashboards/file_reader.go b/pkg/services/provisioning/dashboards/file_reader.go index bf074d96b4e..94de45339c4 100644 --- a/pkg/services/provisioning/dashboards/file_reader.go +++ b/pkg/services/provisioning/dashboards/file_reader.go @@ -94,7 +94,7 @@ func (fr *FileReader) walkDisk(ctx context.Context) error { return err } - provisionedDashboardRefs, err := getProvisionedDashboardsByPath(fr.dashboardProvisioningService, fr.Cfg.Name) + provisionedDashboardRefs, err := getProvisionedDashboardsByPath(ctx, fr.dashboardProvisioningService, fr.Cfg.Name) if err != nil { return err } @@ -279,9 +279,9 @@ func (fr *FileReader) saveDashboard(ctx context.Context, path string, folderID i return provisioningMetadata, nil } -func getProvisionedDashboardsByPath(service dashboards.DashboardProvisioningService, name string) ( +func getProvisionedDashboardsByPath(ctx context.Context, service dashboards.DashboardProvisioningService, name string) ( map[string]*models.DashboardProvisioning, error) { - arr, err := service.GetProvisionedDashboardData(name) + arr, err := service.GetProvisionedDashboardData(ctx, name) if err != nil { return nil, err } diff --git a/pkg/services/publicdashboards/api/api_test.go b/pkg/services/publicdashboards/api/api_test.go index 494bedb457b..e7e3676418f 100644 --- a/pkg/services/publicdashboards/api/api_test.go +++ b/pkg/services/publicdashboards/api/api_test.go @@ -27,6 +27,7 @@ import ( "github.com/grafana/grafana/pkg/services/datasources" datasourcesService "github.com/grafana/grafana/pkg/services/datasources/service" "github.com/grafana/grafana/pkg/services/org" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/publicdashboards" @@ -526,8 +527,8 @@ func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T) } // create dashboard - dashboardStoreService := dashboardStore.ProvideDashboardStore(db, featuremgmt.WithFeatures()) - dashboard, err := dashboardStoreService.SaveDashboard(saveDashboardCmd) + dashboardStoreService := dashboardStore.ProvideDashboardStore(db, featuremgmt.WithFeatures(), tagimpl.ProvideService(db)) + dashboard, err := dashboardStoreService.SaveDashboard(context.Background(), saveDashboardCmd) require.NoError(t, err) // Create public dashboard diff --git a/pkg/services/publicdashboards/database/database_test.go b/pkg/services/publicdashboards/database/database_test.go index 5ac7d281ab5..919c915111a 100644 --- a/pkg/services/publicdashboards/database/database_test.go +++ b/pkg/services/publicdashboards/database/database_test.go @@ -15,6 +15,7 @@ import ( "github.com/grafana/grafana/pkg/services/featuremgmt" . "github.com/grafana/grafana/pkg/services/publicdashboards/models" "github.com/grafana/grafana/pkg/services/sqlstore" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/util" ) @@ -36,7 +37,7 @@ func TestIntegrationGetDashboard(t *testing.T) { setup := func() { sqlStore = sqlstore.InitTestDB(t) - dashboardStore = dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore = dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) publicdashboardStore = ProvideStore(sqlStore) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true) } @@ -60,7 +61,7 @@ func TestIntegrationGetPublicDashboard(t *testing.T) { setup := func() { sqlStore = sqlstore.InitTestDB(t) - dashboardStore = dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore = dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) publicdashboardStore = ProvideStore(sqlStore) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true) } @@ -203,7 +204,7 @@ func TestIntegrationGetPublicDashboardConfig(t *testing.T) { setup := func() { sqlStore = sqlstore.InitTestDB(t) - dashboardStore = dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore = dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) publicdashboardStore = ProvideStore(sqlStore) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true) } @@ -257,7 +258,7 @@ func TestIntegrationSavePublicDashboardConfig(t *testing.T) { setup := func() { sqlStore = sqlstore.InitTestDB(t, sqlstore.InitTestDBOpt{FeatureFlags: []string{featuremgmt.FlagPublicDashboards}}) - dashboardStore = dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore = dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) publicdashboardStore = ProvideStore(sqlStore) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true) savedDashboard2 = insertTestDashboard(t, dashboardStore, "testDashie2", 1, 0, true) @@ -318,7 +319,7 @@ func TestIntegrationUpdatePublicDashboard(t *testing.T) { setup := func() { sqlStore = sqlstore.InitTestDB(t, sqlstore.InitTestDBOpt{FeatureFlags: []string{featuremgmt.FlagPublicDashboards}}) - dashboardStore = dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore = dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) publicdashboardStore = ProvideStore(sqlStore) savedDashboard = insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true) anotherSavedDashboard = insertTestDashboard(t, dashboardStore, "test another Dashie", 1, 0, true) @@ -401,7 +402,7 @@ func insertTestDashboard(t *testing.T, dashboardStore *dashboardsDB.DashboardSto "tags": tags, }), } - dash, err := dashboardStore.SaveDashboard(cmd) + dash, err := dashboardStore.SaveDashboard(context.Background(), cmd) require.NoError(t, err) require.NotNil(t, dash) dash.Data.Set("id", dash.Id) diff --git a/pkg/services/publicdashboards/service/service_test.go b/pkg/services/publicdashboards/service/service_test.go index 81e130b4833..3d3613df6a9 100644 --- a/pkg/services/publicdashboards/service/service_test.go +++ b/pkg/services/publicdashboards/service/service_test.go @@ -7,6 +7,7 @@ import ( "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/publicdashboards/internal" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" "github.com/google/uuid" @@ -117,7 +118,7 @@ func TestGetPublicDashboard(t *testing.T) { func TestSavePublicDashboard(t *testing.T) { t.Run("Saving public dashboard", func(t *testing.T) { sqlStore := sqlstore.InitTestDB(t) - dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) publicdashboardStore := database.ProvideStore(sqlStore) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}) @@ -161,7 +162,7 @@ func TestSavePublicDashboard(t *testing.T) { t.Run("Validate pubdash has default time setting value", func(t *testing.T) { sqlStore := sqlstore.InitTestDB(t) - dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) publicdashboardStore := database.ProvideStore(sqlStore) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}) @@ -191,7 +192,7 @@ func TestSavePublicDashboard(t *testing.T) { t.Run("Validate pubdash whose dashboard has template variables returns error", func(t *testing.T) { sqlStore := sqlstore.InitTestDB(t) - dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) publicdashboardStore := database.ProvideStore(sqlStore) templateVars := make([]map[string]interface{}, 1) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, templateVars) @@ -220,7 +221,7 @@ func TestSavePublicDashboard(t *testing.T) { func TestUpdatePublicDashboard(t *testing.T) { t.Run("Updating public dashboard", func(t *testing.T) { sqlStore := sqlstore.InitTestDB(t) - dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) publicdashboardStore := database.ProvideStore(sqlStore) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}) @@ -281,7 +282,7 @@ func TestUpdatePublicDashboard(t *testing.T) { t.Run("Updating set empty time settings", func(t *testing.T) { sqlStore := sqlstore.InitTestDB(t) - dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) publicdashboardStore := database.ProvideStore(sqlStore) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}) @@ -331,7 +332,7 @@ func TestUpdatePublicDashboard(t *testing.T) { func TestBuildAnonymousUser(t *testing.T) { sqlStore := sqlstore.InitTestDB(t) - dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}) publicdashboardStore := database.ProvideStore(sqlStore) service := &PublicDashboardServiceImpl{ @@ -352,7 +353,7 @@ func TestBuildAnonymousUser(t *testing.T) { func TestGetMetricRequest(t *testing.T) { sqlStore := sqlstore.InitTestDB(t) - dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) publicdashboardStore := database.ProvideStore(sqlStore) dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}) publicDashboard := &PublicDashboard{ @@ -395,7 +396,7 @@ func TestGetMetricRequest(t *testing.T) { func TestBuildMetricRequest(t *testing.T) { sqlStore := sqlstore.InitTestDB(t) - dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures()) + dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) publicdashboardStore := database.ProvideStore(sqlStore) publicDashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}) @@ -562,7 +563,7 @@ func insertTestDashboard(t *testing.T, dashboardStore *dashboardsDB.DashboardSto }, }), } - dash, err := dashboardStore.SaveDashboard(cmd) + dash, err := dashboardStore.SaveDashboard(context.Background(), cmd) require.NoError(t, err) require.NotNil(t, dash) dash.Data.Set("id", dash.Id) diff --git a/pkg/services/sqlstore/session.go b/pkg/services/sqlstore/session.go index 20b31043fa6..9289acb66ac 100644 --- a/pkg/services/sqlstore/session.go +++ b/pkg/services/sqlstore/session.go @@ -34,13 +34,6 @@ func (ss *SQLStore) NewSession(ctx context.Context) *DBSession { return sess } -func (ss *SQLStore) newSession(ctx context.Context) *DBSession { - sess := &DBSession{Session: ss.engine.NewSession()} - sess.Session = sess.Session.Context(ctx) - - return sess -} - func startSessionOrUseExisting(ctx context.Context, engine *xorm.Engine, beginTran bool) (*DBSession, bool, error) { value := ctx.Value(ContextSessionKey{}) var sess *DBSession diff --git a/pkg/services/sqlstore/tags.go b/pkg/services/sqlstore/tags.go deleted file mode 100644 index 2903d42fd7e..00000000000 --- a/pkg/services/sqlstore/tags.go +++ /dev/null @@ -1,26 +0,0 @@ -package sqlstore - -import "github.com/grafana/grafana/pkg/models" - -// Will insert if needed any new key/value pars and return ids -func EnsureTagsExist(sess *DBSession, tags []*models.Tag) ([]*models.Tag, error) { - for _, tag := range tags { - var existingTag models.Tag - - // check if it exists - exists, err := sess.Table("tag").Where("`key`=? AND `value`=?", tag.Key, tag.Value).Get(&existingTag) - if err != nil { - return nil, err - } - if exists { - tag.Id = existingTag.Id - } else { - _, err := sess.Table("tag").Insert(tag) - if err != nil { - return nil, err - } - } - } - - return tags, nil -} diff --git a/pkg/models/tags.go b/pkg/services/tag/model.go similarity index 95% rename from pkg/models/tags.go rename to pkg/services/tag/model.go index 1b90b7d55ba..c597fd281dc 100644 --- a/pkg/models/tags.go +++ b/pkg/services/tag/model.go @@ -1,11 +1,11 @@ -package models +package tag import ( "strings" ) type Tag struct { - Id int64 + Id int64 `xorm:"pk autoincr 'id'"` Key string Value string } diff --git a/pkg/models/tags_test.go b/pkg/services/tag/model_test.go similarity index 99% rename from pkg/models/tags_test.go rename to pkg/services/tag/model_test.go index d25540efab8..aaf530ffa94 100644 --- a/pkg/models/tags_test.go +++ b/pkg/services/tag/model_test.go @@ -1,4 +1,4 @@ -package models +package tag import ( "testing" diff --git a/pkg/services/tag/tag.go b/pkg/services/tag/tag.go new file mode 100644 index 00000000000..f915c930460 --- /dev/null +++ b/pkg/services/tag/tag.go @@ -0,0 +1,9 @@ +package tag + +import ( + "context" +) + +type Service interface { + EnsureTagsExist(ctx context.Context, tags []*Tag) ([]*Tag, error) +} diff --git a/pkg/services/tag/tagimpl/store.go b/pkg/services/tag/tagimpl/store.go new file mode 100644 index 00000000000..a0224a5abec --- /dev/null +++ b/pkg/services/tag/tagimpl/store.go @@ -0,0 +1,39 @@ +package tagimpl + +import ( + "context" + + "github.com/grafana/grafana/pkg/services/sqlstore" + "github.com/grafana/grafana/pkg/services/sqlstore/db" + "github.com/grafana/grafana/pkg/services/tag" +) + +type store interface { + EnsureTagsExist(context.Context, []*tag.Tag) ([]*tag.Tag, error) +} + +type sqlStore struct { + db db.DB +} + +func (s *sqlStore) EnsureTagsExist(ctx context.Context, tags []*tag.Tag) ([]*tag.Tag, error) { + err := s.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { + for _, tagelement := range tags { + var existingTag tag.Tag + exists, err := sess.Table("tag").Where("`key`=? AND `value`=?", tagelement.Key, tagelement.Value).Get(&existingTag) + if err != nil { + return err + } + if exists { + tagelement.Id = existingTag.Id + } else { + _, err := sess.Table("tag").Insert(tagelement) + if err != nil { + return err + } + } + } + return nil + }) + return tags, err +} diff --git a/pkg/services/sqlstore/tags_test.go b/pkg/services/tag/tagimpl/store_test.go similarity index 57% rename from pkg/services/sqlstore/tags_test.go rename to pkg/services/tag/tagimpl/store_test.go index e076c402592..5d7130ba468 100644 --- a/pkg/services/sqlstore/tags_test.go +++ b/pkg/services/tag/tagimpl/store_test.go @@ -1,10 +1,11 @@ -package sqlstore +package tagimpl import ( "context" "testing" - "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/sqlstore" + "github.com/grafana/grafana/pkg/services/tag" "github.com/stretchr/testify/require" ) @@ -13,15 +14,15 @@ func TestIntegrationSavingTags(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } - ss := InitTestDB(t) - - tagPairs := []*models.Tag{ + ss := sqlstore.InitTestDB(t) + store := sqlStore{db: ss} + tagPairs := []*tag.Tag{ {Key: "outage"}, {Key: "type", Value: "outage"}, {Key: "server", Value: "server-1"}, {Key: "error"}, } - tags, err := EnsureTagsExist(ss.newSession(context.Background()), tagPairs) + tags, err := store.EnsureTagsExist(context.Background(), tagPairs) require.Nil(t, err) require.Equal(t, 4, len(tags)) diff --git a/pkg/services/tag/tagimpl/tag.go b/pkg/services/tag/tagimpl/tag.go new file mode 100644 index 00000000000..61db7f161d1 --- /dev/null +++ b/pkg/services/tag/tagimpl/tag.go @@ -0,0 +1,24 @@ +package tagimpl + +import ( + "context" + + "github.com/grafana/grafana/pkg/services/sqlstore/db" + "github.com/grafana/grafana/pkg/services/tag" +) + +type Service struct { + store store +} + +func ProvideService(db db.DB) *Service { + return &Service{ + store: &sqlStore{ + db: db, + }, + } +} + +func (s *Service) EnsureTagsExist(ctx context.Context, tags []*tag.Tag) ([]*tag.Tag, error) { + return s.store.EnsureTagsExist(ctx, tags) +}