From fa9857499b50b68c833e673132f63cce8c683902 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Tue, 14 Sep 2021 16:08:04 +0200 Subject: [PATCH] Chore: GetDashboardQuery should be dispatched using DispatchCtx (#36877) * Chore: GetDashboardQuery should be dispatched using DispatchCtx * Fix after merge * Changes after review * Various fixes * Use GetDashboardCtx function instead of GetDashboard --- pkg/api/dashboard.go | 5 +- pkg/api/folder.go | 14 +++--- pkg/api/folder_permission.go | 4 +- pkg/api/folder_test.go | 13 ++--- pkg/services/dashboards/acl_service.go | 3 +- pkg/services/dashboards/dashboard_service.go | 3 +- pkg/services/dashboards/folder_service.go | 47 ++++++++++--------- .../dashboards/folder_service_test.go | 23 ++++----- pkg/services/libraryelements/database.go | 27 ++++++----- pkg/services/libraryelements/guard.go | 6 ++- .../libraryelements/libraryelements_test.go | 2 +- .../librarypanels/librarypanels_test.go | 2 +- pkg/services/live/features/dashboard.go | 8 ++-- pkg/services/ngalert/api/api_prometheus.go | 2 +- pkg/services/ngalert/api/api_ruler.go | 12 ++--- pkg/services/ngalert/schedule/testing.go | 5 +- pkg/services/ngalert/state/manager.go | 3 +- pkg/services/ngalert/store/alert_rule.go | 12 ++--- .../provisioning/dashboards/dashboard.go | 6 +-- .../provisioning/dashboards/dashboard_mock.go | 6 +-- .../provisioning/dashboards/file_reader.go | 20 ++++---- .../dashboards/file_reader_test.go | 29 ++++++------ .../provisioning/dashboards/validator_test.go | 13 ++--- pkg/services/provisioning/provisioning.go | 2 +- .../provisioning/provisioning_test.go | 2 +- pkg/services/sqlstore/dashboard.go | 2 +- pkg/services/sqlstore/dashboard_test.go | 10 ++-- .../sqlstore/dashboard_version_test.go | 3 +- 28 files changed, 149 insertions(+), 135 deletions(-) diff --git a/pkg/api/dashboard.go b/pkg/api/dashboard.go index 5c4894903f6..28ae5f8e7c5 100644 --- a/pkg/api/dashboard.go +++ b/pkg/api/dashboard.go @@ -276,12 +276,13 @@ func (hs *HTTPServer) deleteDashboard(c *models.ReqContext) response.Response { } func (hs *HTTPServer) PostDashboard(c *models.ReqContext, cmd models.SaveDashboardCommand) response.Response { + ctx := c.Req.Context() var err error cmd.OrgId = c.OrgId cmd.UserId = c.UserId if cmd.FolderUid != "" { folders := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore) - folder, err := folders.GetFolderByUID(cmd.FolderUid) + folder, err := folders.GetFolderByUID(ctx, cmd.FolderUid) if err != nil { if errors.Is(err, models.ErrFolderNotFound) { return response.Error(400, "Folder not found", err) @@ -361,7 +362,7 @@ func (hs *HTTPServer) PostDashboard(c *models.ReqContext, cmd models.SaveDashboa if hs.Cfg.EditorsCanAdmin && newDashboard { inFolder := cmd.FolderId > 0 - err := dashSvc.MakeUserAdmin(cmd.OrgId, cmd.UserId, dashboard.Id, !inFolder) + err := dashSvc.MakeUserAdmin(ctx, cmd.OrgId, cmd.UserId, dashboard.Id, !inFolder) if err != nil { hs.log.Error("Could not make user admin", "dashboard", dashboard.Title, "user", c.SignedInUser.UserId, "error", err) } diff --git a/pkg/api/folder.go b/pkg/api/folder.go index 5fd1cf37628..ba3ee1bd35d 100644 --- a/pkg/api/folder.go +++ b/pkg/api/folder.go @@ -17,7 +17,7 @@ import ( func (hs *HTTPServer) GetFolders(c *models.ReqContext) response.Response { s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore) - folders, err := s.GetFolders(c.QueryInt64("limit"), c.QueryInt64("page")) + folders, err := s.GetFolders(c.Req.Context(), c.QueryInt64("limit"), c.QueryInt64("page")) if err != nil { return apierrors.ToFolderErrorResponse(err) @@ -38,7 +38,7 @@ func (hs *HTTPServer) GetFolders(c *models.ReqContext) response.Response { func (hs *HTTPServer) GetFolderByUID(c *models.ReqContext) response.Response { s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore) - folder, err := s.GetFolderByUID(c.Params(":uid")) + folder, err := s.GetFolderByUID(c.Req.Context(), c.Params(":uid")) if err != nil { return apierrors.ToFolderErrorResponse(err) } @@ -49,7 +49,7 @@ func (hs *HTTPServer) GetFolderByUID(c *models.ReqContext) response.Response { func (hs *HTTPServer) GetFolderByID(c *models.ReqContext) response.Response { s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore) - folder, err := s.GetFolderByID(c.ParamsInt64(":id")) + folder, err := s.GetFolderByID(c.Req.Context(), c.ParamsInt64(":id")) if err != nil { return apierrors.ToFolderErrorResponse(err) } @@ -60,13 +60,13 @@ func (hs *HTTPServer) GetFolderByID(c *models.ReqContext) response.Response { func (hs *HTTPServer) CreateFolder(c *models.ReqContext, cmd models.CreateFolderCommand) response.Response { s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore) - folder, err := s.CreateFolder(cmd.Title, cmd.Uid) + folder, err := s.CreateFolder(c.Req.Context(), cmd.Title, cmd.Uid) if err != nil { return apierrors.ToFolderErrorResponse(err) } if hs.Cfg.EditorsCanAdmin { - if err := s.MakeUserAdmin(c.OrgId, c.SignedInUser.UserId, folder.Id, true); err != nil { + if err := s.MakeUserAdmin(c.Req.Context(), c.OrgId, c.SignedInUser.UserId, folder.Id, true); err != nil { hs.log.Error("Could not make user admin", "folder", folder.Title, "user", c.SignedInUser.UserId, "error", err) } @@ -78,7 +78,7 @@ func (hs *HTTPServer) CreateFolder(c *models.ReqContext, cmd models.CreateFolder func (hs *HTTPServer) UpdateFolder(c *models.ReqContext, cmd models.UpdateFolderCommand) response.Response { s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore) - err := s.UpdateFolder(c.Params(":uid"), &cmd) + err := s.UpdateFolder(c.Req.Context(), c.Params(":uid"), &cmd) if err != nil { return apierrors.ToFolderErrorResponse(err) } @@ -97,7 +97,7 @@ func (hs *HTTPServer) DeleteFolder(c *models.ReqContext) response.Response { // return apierrors.ToFolderErrorResponse(err) } - f, err := s.DeleteFolder(c.Params(":uid"), c.QueryBool("forceDeleteRules")) + f, err := s.DeleteFolder(c.Req.Context(), c.Params(":uid"), c.QueryBool("forceDeleteRules")) if err != nil { return apierrors.ToFolderErrorResponse(err) } diff --git a/pkg/api/folder_permission.go b/pkg/api/folder_permission.go index 9009da442c4..bc218dc5059 100644 --- a/pkg/api/folder_permission.go +++ b/pkg/api/folder_permission.go @@ -15,7 +15,7 @@ import ( func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Response { s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore) - folder, err := s.GetFolderByUID(c.Params(":uid")) + folder, err := s.GetFolderByUID(c.Req.Context(), c.Params(":uid")) if err != nil { return apierrors.ToFolderErrorResponse(err) @@ -63,7 +63,7 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext, apiCmd dtos. } s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore) - folder, err := s.GetFolderByUID(c.Params(":uid")) + folder, err := s.GetFolderByUID(c.Req.Context(), c.Params(":uid")) if err != nil { return apierrors.ToFolderErrorResponse(err) } diff --git a/pkg/api/folder_test.go b/pkg/api/folder_test.go index 31b7021f075..a50d2338c93 100644 --- a/pkg/api/folder_test.go +++ b/pkg/api/folder_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "fmt" "testing" @@ -217,28 +218,28 @@ type fakeFolderService struct { DeletedFolderUids []string } -func (s *fakeFolderService) GetFolders(limit int64, page int64) ([]*models.Folder, error) { +func (s *fakeFolderService) GetFolders(ctx context.Context, limit int64, page int64) ([]*models.Folder, error) { return s.GetFoldersResult, s.GetFoldersError } -func (s *fakeFolderService) GetFolderByID(id int64) (*models.Folder, error) { +func (s *fakeFolderService) GetFolderByID(ctx context.Context, id int64) (*models.Folder, error) { return s.GetFolderByIDResult, s.GetFolderByIDError } -func (s *fakeFolderService) GetFolderByUID(uid string) (*models.Folder, error) { +func (s *fakeFolderService) GetFolderByUID(ctx context.Context, uid string) (*models.Folder, error) { return s.GetFolderByUIDResult, s.GetFolderByUIDError } -func (s *fakeFolderService) CreateFolder(title, uid string) (*models.Folder, error) { +func (s *fakeFolderService) CreateFolder(ctx context.Context, title, uid string) (*models.Folder, error) { return s.CreateFolderResult, s.CreateFolderError } -func (s *fakeFolderService) UpdateFolder(existingUID string, cmd *models.UpdateFolderCommand) error { +func (s *fakeFolderService) UpdateFolder(ctx context.Context, existingUID string, cmd *models.UpdateFolderCommand) error { cmd.Result = s.UpdateFolderResult return s.UpdateFolderError } -func (s *fakeFolderService) DeleteFolder(uid string, forceDeleteRules bool) (*models.Folder, error) { +func (s *fakeFolderService) DeleteFolder(ctx context.Context, uid string, forceDeleteRules bool) (*models.Folder, error) { s.DeletedFolderUids = append(s.DeletedFolderUids, uid) return s.DeleteFolderResult, s.DeleteFolderError } diff --git a/pkg/services/dashboards/acl_service.go b/pkg/services/dashboards/acl_service.go index b344ab3775c..f445e515e7d 100644 --- a/pkg/services/dashboards/acl_service.go +++ b/pkg/services/dashboards/acl_service.go @@ -1,12 +1,13 @@ package dashboards import ( + "context" "time" "github.com/grafana/grafana/pkg/models" ) -func (dr *dashboardServiceImpl) MakeUserAdmin(orgID int64, userID int64, dashboardID int64, setViewAndEditPermissions bool) error { +func (dr *dashboardServiceImpl) MakeUserAdmin(ctx context.Context, orgID int64, userID int64, dashboardID int64, setViewAndEditPermissions bool) error { rtEditor := models.ROLE_EDITOR rtViewer := models.ROLE_VIEWER diff --git a/pkg/services/dashboards/dashboard_service.go b/pkg/services/dashboards/dashboard_service.go index 2049082f667..4df63285df1 100644 --- a/pkg/services/dashboards/dashboard_service.go +++ b/pkg/services/dashboards/dashboard_service.go @@ -1,6 +1,7 @@ package dashboards import ( + "context" "fmt" "strings" "time" @@ -23,7 +24,7 @@ type DashboardService interface { SaveDashboard(dto *SaveDashboardDTO, allowUiUpdate bool) (*models.Dashboard, error) ImportDashboard(dto *SaveDashboardDTO) (*models.Dashboard, error) DeleteDashboard(dashboardId int64, orgId int64) error - MakeUserAdmin(orgID int64, userID, dashboardID int64, setViewAndEditPermissions bool) error + MakeUserAdmin(ctx context.Context, orgID int64, userID, dashboardID int64, setViewAndEditPermissions bool) error } // DashboardProvisioningService is a service for operating on provisioned dashboards. diff --git a/pkg/services/dashboards/folder_service.go b/pkg/services/dashboards/folder_service.go index 662de976b8e..97cad653bc9 100644 --- a/pkg/services/dashboards/folder_service.go +++ b/pkg/services/dashboards/folder_service.go @@ -1,6 +1,7 @@ package dashboards import ( + "context" "errors" "strings" @@ -13,14 +14,14 @@ import ( // FolderService is a service for operating on folders. type FolderService interface { - GetFolders(limit int64, page int64) ([]*models.Folder, error) - GetFolderByID(id int64) (*models.Folder, error) - GetFolderByUID(uid string) (*models.Folder, error) - GetFolderByTitle(title string) (*models.Folder, error) - CreateFolder(title, uid string) (*models.Folder, error) - UpdateFolder(uid string, cmd *models.UpdateFolderCommand) error - DeleteFolder(uid string, forceDeleteRules bool) (*models.Folder, error) - MakeUserAdmin(orgID int64, userID, folderID int64, setViewAndEditPermissions bool) error + GetFolders(ctx context.Context, limit int64, page int64) ([]*models.Folder, error) + GetFolderByID(ctx context.Context, id int64) (*models.Folder, error) + GetFolderByUID(ctx context.Context, uid string) (*models.Folder, error) + GetFolderByTitle(ctx context.Context, title string) (*models.Folder, error) + CreateFolder(ctx context.Context, title, uid string) (*models.Folder, error) + UpdateFolder(ctx context.Context, uid string, cmd *models.UpdateFolderCommand) error + DeleteFolder(ctx context.Context, uid string, forceDeleteRules bool) (*models.Folder, error) + MakeUserAdmin(ctx context.Context, orgID int64, userID, folderID int64, setViewAndEditPermissions bool) error } // NewFolderService is a factory for creating a new folder service. @@ -32,7 +33,7 @@ var NewFolderService = func(orgID int64, user *models.SignedInUser, store dashbo } } -func (dr *dashboardServiceImpl) GetFolders(limit int64, page int64) ([]*models.Folder, error) { +func (dr *dashboardServiceImpl) GetFolders(ctx context.Context, limit int64, page int64) ([]*models.Folder, error) { searchQuery := search.Query{ SignedInUser: dr.user, DashboardIds: make([]int64, 0), @@ -61,12 +62,12 @@ func (dr *dashboardServiceImpl) GetFolders(limit int64, page int64) ([]*models.F return folders, nil } -func (dr *dashboardServiceImpl) GetFolderByID(id int64) (*models.Folder, error) { +func (dr *dashboardServiceImpl) GetFolderByID(ctx context.Context, id int64) (*models.Folder, error) { if id == 0 { return &models.Folder{Id: id, Title: "General"}, nil } query := models.GetDashboardQuery{OrgId: dr.orgId, Id: id} - dashFolder, err := getFolder(query) + dashFolder, err := getFolder(ctx, query) if err != nil { return nil, toFolderError(err) } @@ -82,9 +83,9 @@ func (dr *dashboardServiceImpl) GetFolderByID(id int64) (*models.Folder, error) return dashToFolder(dashFolder), nil } -func (dr *dashboardServiceImpl) GetFolderByUID(uid string) (*models.Folder, error) { +func (dr *dashboardServiceImpl) GetFolderByUID(ctx context.Context, uid string) (*models.Folder, error) { query := models.GetDashboardQuery{OrgId: dr.orgId, Uid: uid} - dashFolder, err := getFolder(query) + dashFolder, err := getFolder(ctx, query) if err != nil { return nil, toFolderError(err) @@ -101,7 +102,7 @@ func (dr *dashboardServiceImpl) GetFolderByUID(uid string) (*models.Folder, erro return dashToFolder(dashFolder), nil } -func (dr *dashboardServiceImpl) GetFolderByTitle(title string) (*models.Folder, error) { +func (dr *dashboardServiceImpl) GetFolderByTitle(ctx context.Context, title string) (*models.Folder, error) { dashFolder, err := dr.dashboardStore.GetFolderByTitle(dr.orgId, title) if err != nil { return nil, toFolderError(err) @@ -118,7 +119,7 @@ func (dr *dashboardServiceImpl) GetFolderByTitle(title string) (*models.Folder, return dashToFolder(dashFolder), nil } -func (dr *dashboardServiceImpl) CreateFolder(title, uid string) (*models.Folder, error) { +func (dr *dashboardServiceImpl) CreateFolder(ctx context.Context, title, uid string) (*models.Folder, error) { dashFolder := models.NewDashboardFolder(title) dashFolder.OrgId = dr.orgId dashFolder.SetUid(strings.TrimSpace(uid)) @@ -147,7 +148,7 @@ func (dr *dashboardServiceImpl) CreateFolder(title, uid string) (*models.Folder, } query := models.GetDashboardQuery{OrgId: dr.orgId, Id: dash.Id} - dashFolder, err = getFolder(query) + dashFolder, err = getFolder(ctx, query) if err != nil { return nil, toFolderError(err) } @@ -155,9 +156,9 @@ func (dr *dashboardServiceImpl) CreateFolder(title, uid string) (*models.Folder, return dashToFolder(dashFolder), nil } -func (dr *dashboardServiceImpl) UpdateFolder(existingUid string, cmd *models.UpdateFolderCommand) error { +func (dr *dashboardServiceImpl) UpdateFolder(ctx context.Context, existingUid string, cmd *models.UpdateFolderCommand) error { query := models.GetDashboardQuery{OrgId: dr.orgId, Uid: existingUid} - dashFolder, err := getFolder(query) + dashFolder, err := getFolder(ctx, query) if err != nil { return toFolderError(err) } @@ -182,7 +183,7 @@ func (dr *dashboardServiceImpl) UpdateFolder(existingUid string, cmd *models.Upd } query = models.GetDashboardQuery{OrgId: dr.orgId, Id: dash.Id} - dashFolder, err = getFolder(query) + dashFolder, err = getFolder(ctx, query) if err != nil { return toFolderError(err) } @@ -192,9 +193,9 @@ func (dr *dashboardServiceImpl) UpdateFolder(existingUid string, cmd *models.Upd return nil } -func (dr *dashboardServiceImpl) DeleteFolder(uid string, forceDeleteRules bool) (*models.Folder, error) { +func (dr *dashboardServiceImpl) DeleteFolder(ctx context.Context, uid string, forceDeleteRules bool) (*models.Folder, error) { query := models.GetDashboardQuery{OrgId: dr.orgId, Uid: uid} - dashFolder, err := getFolder(query) + dashFolder, err := getFolder(ctx, query) if err != nil { return nil, toFolderError(err) } @@ -215,8 +216,8 @@ func (dr *dashboardServiceImpl) DeleteFolder(uid string, forceDeleteRules bool) return dashToFolder(dashFolder), nil } -func getFolder(query models.GetDashboardQuery) (*models.Dashboard, error) { - if err := bus.Dispatch(&query); err != nil { +func getFolder(ctx context.Context, query models.GetDashboardQuery) (*models.Dashboard, error) { + if err := bus.DispatchCtx(ctx, &query); err != nil { return nil, toFolderError(err) } diff --git a/pkg/services/dashboards/folder_service_test.go b/pkg/services/dashboards/folder_service_test.go index 122f0ad1cc3..84e9402be45 100644 --- a/pkg/services/dashboards/folder_service_test.go +++ b/pkg/services/dashboards/folder_service_test.go @@ -1,6 +1,7 @@ package dashboards import ( + "context" "testing" "github.com/grafana/grafana/pkg/bus" @@ -38,28 +39,28 @@ func TestFolderService(t *testing.T) { } t.Run("When get folder by id should return access denied error", func(t *testing.T) { - _, err := service.GetFolderByID(1) + _, err := service.GetFolderByID(context.Background(), 1) require.Equal(t, err, models.ErrFolderAccessDenied) }) t.Run("When get folder by id, with id = 0 should return default folder", func(t *testing.T) { - folder, err := service.GetFolderByID(0) + folder, err := service.GetFolderByID(context.Background(), 0) require.NoError(t, err) require.Equal(t, folder, &models.Folder{Id: 0, Title: "General"}) }) t.Run("When get folder by uid should return access denied error", func(t *testing.T) { - _, err := service.GetFolderByUID("uid") + _, err := service.GetFolderByUID(context.Background(), "uid") require.Equal(t, err, models.ErrFolderAccessDenied) }) t.Run("When creating folder should return access denied error", func(t *testing.T) { - _, err := service.CreateFolder("Folder", "") + _, err := service.CreateFolder(context.Background(), "Folder", "") require.Equal(t, err, models.ErrFolderAccessDenied) }) t.Run("When updating folder should return access denied error", func(t *testing.T) { - err := service.UpdateFolder("uid", &models.UpdateFolderCommand{ + err := service.UpdateFolder(context.Background(), "uid", &models.UpdateFolderCommand{ Uid: "uid", Title: "Folder", }) @@ -67,7 +68,7 @@ func TestFolderService(t *testing.T) { }) t.Run("When deleting folder by uid should return access denied error", func(t *testing.T) { - _, err := service.DeleteFolder("uid", false) + _, err := service.DeleteFolder(context.Background(), "uid", false) require.Error(t, err) require.Equal(t, err, models.ErrFolderAccessDenied) }) @@ -108,12 +109,12 @@ func TestFolderService(t *testing.T) { }) t.Run("When creating folder should not return access denied error", func(t *testing.T) { - _, err := service.CreateFolder("Folder", "") + _, err := service.CreateFolder(context.Background(), "Folder", "") require.NoError(t, err) }) t.Run("When updating folder should not return access denied error", func(t *testing.T) { - err := service.UpdateFolder("uid", &models.UpdateFolderCommand{ + err := service.UpdateFolder(context.Background(), "uid", &models.UpdateFolderCommand{ Uid: "uid", Title: "Folder", }) @@ -121,7 +122,7 @@ func TestFolderService(t *testing.T) { }) t.Run("When deleting folder by uid should not return access denied error", func(t *testing.T) { - _, err := service.DeleteFolder("uid", false) + _, err := service.DeleteFolder(context.Background(), "uid", false) require.NoError(t, err) }) @@ -144,14 +145,14 @@ func TestFolderService(t *testing.T) { }) t.Run("When get folder by id should return folder", func(t *testing.T) { - f, _ := service.GetFolderByID(1) + f, _ := service.GetFolderByID(context.Background(), 1) require.Equal(t, f.Id, dashFolder.Id) require.Equal(t, f.Uid, dashFolder.Uid) require.Equal(t, f.Title, dashFolder.Title) }) t.Run("When get folder by uid should return folder", func(t *testing.T) { - f, _ := service.GetFolderByUID("uid") + f, _ := service.GetFolderByUID(context.Background(), "uid") require.Equal(t, f.Id, dashFolder.Id) require.Equal(t, f.Uid, dashFolder.Uid) require.Equal(t, f.Title, dashFolder.Title) diff --git a/pkg/services/libraryelements/database.go b/pkg/services/libraryelements/database.go index ddc5ed18342..b7832abe499 100644 --- a/pkg/services/libraryelements/database.go +++ b/pkg/services/libraryelements/database.go @@ -1,6 +1,7 @@ package libraryelements import ( + "context" "encoding/json" "errors" "fmt" @@ -123,8 +124,8 @@ func (l *LibraryElementService) createLibraryElement(c *models.ReqContext, cmd C return LibraryElementDTO{}, err } - err := l.SQLStore.WithTransactionalDbSession(c.Context.Req.Context(), func(session *sqlstore.DBSession) error { - if err := l.requirePermissionsOnFolder(c.SignedInUser, cmd.FolderID); err != nil { + err := l.SQLStore.WithTransactionalDbSession(c.Req.Context(), func(session *sqlstore.DBSession) error { + if err := l.requirePermissionsOnFolder(c.Req.Context(), c.SignedInUser, cmd.FolderID); err != nil { return err } if _, err := session.Insert(&element); err != nil { @@ -169,12 +170,12 @@ func (l *LibraryElementService) createLibraryElement(c *models.ReqContext, cmd C // deleteLibraryElement deletes a library element. func (l *LibraryElementService) deleteLibraryElement(c *models.ReqContext, uid string) error { - return l.SQLStore.WithTransactionalDbSession(c.Context.Req.Context(), func(session *sqlstore.DBSession) error { + return l.SQLStore.WithTransactionalDbSession(c.Req.Context(), func(session *sqlstore.DBSession) error { element, err := getLibraryElement(l.SQLStore.Dialect, session, uid, c.SignedInUser.OrgId) if err != nil { return err } - if err := l.requirePermissionsOnFolder(c.SignedInUser, element.FolderID); err != nil { + if err := l.requirePermissionsOnFolder(c.Req.Context(), c.SignedInUser, element.FolderID); err != nil { return err } var connectionIDs []struct { @@ -408,7 +409,7 @@ func (l *LibraryElementService) getAllLibraryElements(c *models.ReqContext, quer return result, err } -func (l *LibraryElementService) handleFolderIDPatches(elementToPatch *LibraryElement, fromFolderID int64, toFolderID int64, user *models.SignedInUser) error { +func (l *LibraryElementService) handleFolderIDPatches(ctx context.Context, elementToPatch *LibraryElement, fromFolderID int64, toFolderID int64, user *models.SignedInUser) error { // FolderID was not provided in the PATCH request if toFolderID == -1 { toFolderID = fromFolderID @@ -416,13 +417,13 @@ func (l *LibraryElementService) handleFolderIDPatches(elementToPatch *LibraryEle // FolderID was provided in the PATCH request if toFolderID != -1 && toFolderID != fromFolderID { - if err := l.requirePermissionsOnFolder(user, toFolderID); err != nil { + if err := l.requirePermissionsOnFolder(ctx, user, toFolderID); err != nil { return err } } // Always check permissions for the folder where library element resides - if err := l.requirePermissionsOnFolder(user, fromFolderID); err != nil { + if err := l.requirePermissionsOnFolder(ctx, user, fromFolderID); err != nil { return err } @@ -437,7 +438,7 @@ func (l *LibraryElementService) patchLibraryElement(c *models.ReqContext, cmd pa if err := l.requireSupportedElementKind(cmd.Kind); err != nil { return LibraryElementDTO{}, err } - err := l.SQLStore.WithTransactionalDbSession(c.Context.Req.Context(), func(session *sqlstore.DBSession) error { + err := l.SQLStore.WithTransactionalDbSession(c.Req.Context(), func(session *sqlstore.DBSession) error { elementInDB, err := getLibraryElement(l.SQLStore.Dialect, session, uid, c.SignedInUser.OrgId) if err != nil { return err @@ -484,7 +485,7 @@ func (l *LibraryElementService) patchLibraryElement(c *models.ReqContext, cmd pa if cmd.Model == nil { libraryElement.Model = elementInDB.Model } - if err := l.handleFolderIDPatches(&libraryElement, elementInDB.FolderID, cmd.FolderID, c.SignedInUser); err != nil { + if err := l.handleFolderIDPatches(c.Req.Context(), &libraryElement, elementInDB.FolderID, cmd.FolderID, c.SignedInUser); err != nil { return err } if err := syncFieldsWithModel(&libraryElement); err != nil { @@ -633,7 +634,7 @@ func (l *LibraryElementService) getElementsForDashboardID(c *models.ReqContext, // connectElementsToDashboardID adds connections for all elements Library Elements in a Dashboard. func (l *LibraryElementService) connectElementsToDashboardID(c *models.ReqContext, elementUIDs []string, dashboardID int64) error { - err := l.SQLStore.WithTransactionalDbSession(c.Context.Req.Context(), func(session *sqlstore.DBSession) error { + err := l.SQLStore.WithTransactionalDbSession(c.Req.Context(), func(session *sqlstore.DBSession) error { _, err := session.Exec("DELETE FROM "+models.LibraryElementConnectionTableName+" WHERE kind=1 AND connection_id=?", dashboardID) if err != nil { return err @@ -643,7 +644,7 @@ func (l *LibraryElementService) connectElementsToDashboardID(c *models.ReqContex if err != nil { return err } - if err := l.requirePermissionsOnFolder(c.SignedInUser, element.FolderID); err != nil { + if err := l.requirePermissionsOnFolder(c.Req.Context(), c.SignedInUser, element.FolderID); err != nil { return err } @@ -680,7 +681,7 @@ func (l *LibraryElementService) disconnectElementsFromDashboardID(c *models.ReqC // deleteLibraryElementsInFolderUID deletes all Library Elements in a folder. func (l *LibraryElementService) deleteLibraryElementsInFolderUID(c *models.ReqContext, folderUID string) error { - return l.SQLStore.WithTransactionalDbSession(c.Context.Req.Context(), func(session *sqlstore.DBSession) error { + return l.SQLStore.WithTransactionalDbSession(c.Req.Context(), func(session *sqlstore.DBSession) error { var folderUIDs []struct { ID int64 `xorm:"id"` } @@ -693,7 +694,7 @@ func (l *LibraryElementService) deleteLibraryElementsInFolderUID(c *models.ReqCo } folderID := folderUIDs[0].ID - if err := l.requirePermissionsOnFolder(c.SignedInUser, folderID); err != nil { + if err := l.requirePermissionsOnFolder(c.Req.Context(), c.SignedInUser, folderID); err != nil { return err } var connectionIDs []struct { diff --git a/pkg/services/libraryelements/guard.go b/pkg/services/libraryelements/guard.go index 980eb6cb3f7..9745cefd887 100644 --- a/pkg/services/libraryelements/guard.go +++ b/pkg/services/libraryelements/guard.go @@ -1,6 +1,8 @@ package libraryelements import ( + "context" + "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/guardian" @@ -22,7 +24,7 @@ func (l *LibraryElementService) requireSupportedElementKind(kindAsInt int64) err } } -func (l *LibraryElementService) requirePermissionsOnFolder(user *models.SignedInUser, folderID int64) error { +func (l *LibraryElementService) requirePermissionsOnFolder(ctx context.Context, user *models.SignedInUser, folderID int64) error { if isGeneralFolder(folderID) && user.HasRole(models.ROLE_EDITOR) { return nil } @@ -32,7 +34,7 @@ func (l *LibraryElementService) requirePermissionsOnFolder(user *models.SignedIn } s := dashboards.NewFolderService(user.OrgId, user, l.SQLStore) - folder, err := s.GetFolderByID(folderID) + folder, err := s.GetFolderByID(ctx, folderID) if err != nil { return err } diff --git a/pkg/services/libraryelements/libraryelements_test.go b/pkg/services/libraryelements/libraryelements_test.go index b795d1c550c..ac296bc9eab 100644 --- a/pkg/services/libraryelements/libraryelements_test.go +++ b/pkg/services/libraryelements/libraryelements_test.go @@ -207,7 +207,7 @@ func createFolderWithACL(t *testing.T, sqlStore *sqlstore.SQLStore, title string s := dashboards.NewFolderService(user.OrgId, &user, sqlStore) t.Logf("Creating folder with title and UID %q", title) - folder, err := s.CreateFolder(title, title) + folder, err := s.CreateFolder(context.Background(), title, title) require.NoError(t, err) updateFolderACL(t, sqlStore, folder.Id, items) diff --git a/pkg/services/librarypanels/librarypanels_test.go b/pkg/services/librarypanels/librarypanels_test.go index 7d2e4f6e0b7..cf8ca6b00d7 100644 --- a/pkg/services/librarypanels/librarypanels_test.go +++ b/pkg/services/librarypanels/librarypanels_test.go @@ -1111,7 +1111,7 @@ func createFolderWithACL(t *testing.T, sqlStore *sqlstore.SQLStore, title string s := dashboards.NewFolderService(user.OrgId, &user, sqlStore) t.Logf("Creating folder with title and UID %q", title) - folder, err := s.CreateFolder(title, title) + folder, err := s.CreateFolder(context.Background(), title, title) require.NoError(t, err) updateFolderACL(t, sqlStore, folder.Id, items) diff --git a/pkg/services/live/features/dashboard.go b/pkg/services/live/features/dashboard.go index cd8be5f3cc1..600f3918a67 100644 --- a/pkg/services/live/features/dashboard.go +++ b/pkg/services/live/features/dashboard.go @@ -47,7 +47,7 @@ func (h *DashboardHandler) GetHandlerForPath(_ string) (models.ChannelHandler, e } // OnSubscribe for now allows anyone to subscribe to any dashboard -func (h *DashboardHandler) OnSubscribe(_ context.Context, user *models.SignedInUser, e models.SubscribeEvent) (models.SubscribeReply, backend.SubscribeStreamStatus, error) { +func (h *DashboardHandler) OnSubscribe(ctx context.Context, user *models.SignedInUser, e models.SubscribeEvent) (models.SubscribeReply, backend.SubscribeStreamStatus, error) { parts := strings.Split(e.Path, "/") if parts[0] == "gitops" { // gitops gets all changes for everything, so lets make sure it is an admin user @@ -62,7 +62,7 @@ func (h *DashboardHandler) OnSubscribe(_ context.Context, user *models.SignedInU // make sure can view this dashboard if len(parts) == 2 && parts[0] == "uid" { query := models.GetDashboardQuery{Uid: parts[1], OrgId: user.OrgId} - if err := bus.Dispatch(&query); err != nil { + if err := bus.DispatchCtx(ctx, &query); err != nil { logger.Error("Error getting dashboard", "query", query, "error", err) return models.SubscribeReply{}, backend.SubscribeStreamStatusNotFound, nil } @@ -85,7 +85,7 @@ func (h *DashboardHandler) OnSubscribe(_ context.Context, user *models.SignedInU } // OnPublish is called when someone begins to edit a dashboard -func (h *DashboardHandler) OnPublish(_ context.Context, user *models.SignedInUser, e models.PublishEvent) (models.PublishReply, backend.PublishStreamStatus, error) { +func (h *DashboardHandler) OnPublish(ctx context.Context, user *models.SignedInUser, e models.PublishEvent) (models.PublishReply, backend.PublishStreamStatus, error) { parts := strings.Split(e.Path, "/") if parts[0] == "gitops" { // gitops gets all changes for everything, so lets make sure it is an admin user @@ -109,7 +109,7 @@ func (h *DashboardHandler) OnPublish(_ context.Context, user *models.SignedInUse return models.PublishReply{}, backend.PublishStreamStatusNotFound, fmt.Errorf("ignore???") } query := models.GetDashboardQuery{Uid: parts[1], OrgId: user.OrgId} - if err := bus.Dispatch(&query); err != nil { + if err := bus.DispatchCtx(ctx, &query); err != nil { logger.Error("Unknown dashboard", "query", query) return models.PublishReply{}, backend.PublishStreamStatusNotFound, nil } diff --git a/pkg/services/ngalert/api/api_prometheus.go b/pkg/services/ngalert/api/api_prometheus.go index 7398653d78a..493488efa7c 100644 --- a/pkg/services/ngalert/api/api_prometheus.go +++ b/pkg/services/ngalert/api/api_prometheus.go @@ -61,7 +61,7 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *models.ReqContext) response.Res }, } - namespaceMap, err := srv.store.GetNamespaces(c.OrgId, c.SignedInUser) + namespaceMap, err := srv.store.GetNamespaces(c.Req.Context(), c.OrgId, c.SignedInUser) if err != nil { return ErrResp(http.StatusInternalServerError, err, "failed to get namespaces visible to the user") } diff --git a/pkg/services/ngalert/api/api_ruler.go b/pkg/services/ngalert/api/api_ruler.go index dac1a4a5a7e..e36c2c51f0e 100644 --- a/pkg/services/ngalert/api/api_ruler.go +++ b/pkg/services/ngalert/api/api_ruler.go @@ -31,7 +31,7 @@ type RulerSrv struct { func (srv RulerSrv) RouteDeleteNamespaceRulesConfig(c *models.ReqContext) response.Response { namespaceTitle := c.Params(":Namespace") - namespace, err := srv.store.GetNamespaceByTitle(namespaceTitle, c.SignedInUser.OrgId, c.SignedInUser, true) + namespace, err := srv.store.GetNamespaceByTitle(c.Req.Context(), namespaceTitle, c.SignedInUser.OrgId, c.SignedInUser, true) if err != nil { return toNamespaceErrorResponse(err) } @@ -50,7 +50,7 @@ func (srv RulerSrv) RouteDeleteNamespaceRulesConfig(c *models.ReqContext) respon func (srv RulerSrv) RouteDeleteRuleGroupConfig(c *models.ReqContext) response.Response { namespaceTitle := c.Params(":Namespace") - namespace, err := srv.store.GetNamespaceByTitle(namespaceTitle, c.SignedInUser.OrgId, c.SignedInUser, true) + namespace, err := srv.store.GetNamespaceByTitle(c.Req.Context(), namespaceTitle, c.SignedInUser.OrgId, c.SignedInUser, true) if err != nil { return toNamespaceErrorResponse(err) } @@ -73,7 +73,7 @@ func (srv RulerSrv) RouteDeleteRuleGroupConfig(c *models.ReqContext) response.Re func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *models.ReqContext) response.Response { namespaceTitle := c.Params(":Namespace") - namespace, err := srv.store.GetNamespaceByTitle(namespaceTitle, c.SignedInUser.OrgId, c.SignedInUser, false) + namespace, err := srv.store.GetNamespaceByTitle(c.Req.Context(), namespaceTitle, c.SignedInUser.OrgId, c.SignedInUser, false) if err != nil { return toNamespaceErrorResponse(err) } @@ -114,7 +114,7 @@ func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *models.ReqContext) response. func (srv RulerSrv) RouteGetRulegGroupConfig(c *models.ReqContext) response.Response { namespaceTitle := c.Params(":Namespace") - namespace, err := srv.store.GetNamespaceByTitle(namespaceTitle, c.SignedInUser.OrgId, c.SignedInUser, false) + namespace, err := srv.store.GetNamespaceByTitle(c.Req.Context(), namespaceTitle, c.SignedInUser.OrgId, c.SignedInUser, false) if err != nil { return toNamespaceErrorResponse(err) } @@ -147,7 +147,7 @@ func (srv RulerSrv) RouteGetRulegGroupConfig(c *models.ReqContext) response.Resp } func (srv RulerSrv) RouteGetRulesConfig(c *models.ReqContext) response.Response { - namespaceMap, err := srv.store.GetNamespaces(c.OrgId, c.SignedInUser) + namespaceMap, err := srv.store.GetNamespaces(c.Req.Context(), c.OrgId, c.SignedInUser) if err != nil { return ErrResp(http.StatusInternalServerError, err, "failed to get namespaces visible to the user") } @@ -214,7 +214,7 @@ func (srv RulerSrv) RouteGetRulesConfig(c *models.ReqContext) response.Response func (srv RulerSrv) RoutePostNameRulesConfig(c *models.ReqContext, ruleGroupConfig apimodels.PostableRuleGroupConfig) response.Response { namespaceTitle := c.Params(":Namespace") - namespace, err := srv.store.GetNamespaceByTitle(namespaceTitle, c.SignedInUser.OrgId, c.SignedInUser, true) + namespace, err := srv.store.GetNamespaceByTitle(c.Req.Context(), namespaceTitle, c.SignedInUser.OrgId, c.SignedInUser, true) if err != nil { return toNamespaceErrorResponse(err) } diff --git a/pkg/services/ngalert/schedule/testing.go b/pkg/services/ngalert/schedule/testing.go index c7b39ac98bc..31732d0ee97 100644 --- a/pkg/services/ngalert/schedule/testing.go +++ b/pkg/services/ngalert/schedule/testing.go @@ -1,6 +1,7 @@ package schedule import ( + "context" "encoding/json" "io/ioutil" "net/http" @@ -109,10 +110,10 @@ func (f *fakeRuleStore) GetRuleGroupAlertRules(q *models.ListRuleGroupAlertRules return nil } -func (f *fakeRuleStore) GetNamespaces(_ int64, _ *models2.SignedInUser) (map[string]*models2.Folder, error) { +func (f *fakeRuleStore) GetNamespaces(_ context.Context, _ int64, _ *models2.SignedInUser) (map[string]*models2.Folder, error) { return nil, nil } -func (f *fakeRuleStore) GetNamespaceByTitle(_ string, _ int64, _ *models2.SignedInUser, _ bool) (*models2.Folder, error) { +func (f *fakeRuleStore) GetNamespaceByTitle(_ context.Context, _ string, _ int64, _ *models2.SignedInUser, _ bool) (*models2.Folder, error) { return nil, nil } func (f *fakeRuleStore) GetOrgRuleGroups(_ *models.ListOrgRuleGroupsQuery) error { return nil } diff --git a/pkg/services/ngalert/state/manager.go b/pkg/services/ngalert/state/manager.go index c544e8ece87..bbd2f1381ad 100644 --- a/pkg/services/ngalert/state/manager.go +++ b/pkg/services/ngalert/state/manager.go @@ -1,6 +1,7 @@ package state import ( + "context" "fmt" "strconv" "time" @@ -251,7 +252,7 @@ func (st *Manager) createAlertAnnotation(new eval.State, alertRule *ngModels.Ale OrgId: alertRule.OrgID, } - err = sqlstore.GetDashboard(query) + err = sqlstore.GetDashboardCtx(context.TODO(), query) if err != nil { st.log.Error("error getting dashboard for alert annotation", "dashboardUID", dashUid, "alertRuleUID", alertRule.UID, "error", err.Error()) return diff --git a/pkg/services/ngalert/store/alert_rule.go b/pkg/services/ngalert/store/alert_rule.go index 4faa4a0610b..c1ee47b8071 100644 --- a/pkg/services/ngalert/store/alert_rule.go +++ b/pkg/services/ngalert/store/alert_rule.go @@ -47,8 +47,8 @@ type RuleStore interface { GetOrgAlertRules(query *ngmodels.ListAlertRulesQuery) error GetNamespaceAlertRules(query *ngmodels.ListNamespaceAlertRulesQuery) error GetRuleGroupAlertRules(query *ngmodels.ListRuleGroupAlertRulesQuery) error - GetNamespaces(int64, *models.SignedInUser) (map[string]*models.Folder, error) - GetNamespaceByTitle(string, int64, *models.SignedInUser, bool) (*models.Folder, error) + GetNamespaces(context.Context, int64, *models.SignedInUser) (map[string]*models.Folder, error) + GetNamespaceByTitle(context.Context, string, int64, *models.SignedInUser, bool) (*models.Folder, error) GetOrgRuleGroups(query *ngmodels.ListOrgRuleGroupsQuery) error UpsertAlertRules([]UpsertRule) error UpdateRuleGroup(UpdateRuleGroupCmd) error @@ -372,13 +372,13 @@ func (st DBstore) GetRuleGroupAlertRules(query *ngmodels.ListRuleGroupAlertRules } // GetNamespaces returns the folders that are visible to the user -func (st DBstore) GetNamespaces(orgID int64, user *models.SignedInUser) (map[string]*models.Folder, error) { +func (st DBstore) GetNamespaces(ctx context.Context, orgID int64, user *models.SignedInUser) (map[string]*models.Folder, error) { s := dashboards.NewFolderService(orgID, user, st.SQLStore) namespaceMap := make(map[string]*models.Folder) var page int64 = 1 for { // if limit is negative; it fetches at most 1000 - folders, err := s.GetFolders(-1, page) + folders, err := s.GetFolders(ctx, -1, page) if err != nil { return nil, err } @@ -396,9 +396,9 @@ func (st DBstore) GetNamespaces(orgID int64, user *models.SignedInUser) (map[str } // GetNamespaceByTitle is a handler for retrieving a namespace by its title. Alerting rules follow a Grafana folder-like structure which we call namespaces. -func (st DBstore) GetNamespaceByTitle(namespace string, orgID int64, user *models.SignedInUser, withCanSave bool) (*models.Folder, error) { +func (st DBstore) GetNamespaceByTitle(ctx context.Context, namespace string, orgID int64, user *models.SignedInUser, withCanSave bool) (*models.Folder, error) { s := dashboards.NewFolderService(orgID, user, st.SQLStore) - folder, err := s.GetFolderByTitle(namespace) + folder, err := s.GetFolderByTitle(ctx, namespace) if err != nil { return nil, err } diff --git a/pkg/services/provisioning/dashboards/dashboard.go b/pkg/services/provisioning/dashboards/dashboard.go index bafd171d833..af9399dff90 100644 --- a/pkg/services/provisioning/dashboards/dashboard.go +++ b/pkg/services/provisioning/dashboards/dashboard.go @@ -15,7 +15,7 @@ import ( // DashboardProvisioner is responsible for syncing dashboard from disk to // Grafana's database. type DashboardProvisioner interface { - Provision() error + Provision(ctx context.Context) error PollChanges(ctx context.Context) GetProvisionerResolvedPath(name string) string GetAllowUIUpdatesFromConfig(name string) bool @@ -59,9 +59,9 @@ func New(configDirectory string, store dashboards.Store) (DashboardProvisioner, // Provision scans the disk for dashboards and updates // the database with the latest versions of those dashboards. -func (provider *Provisioner) Provision() error { +func (provider *Provisioner) Provision(ctx context.Context) error { for _, reader := range provider.fileReaders { - if err := reader.walkDisk(); err != nil { + if err := reader.walkDisk(ctx); err != nil { if os.IsNotExist(err) { // don't stop the provisioning service in case the folder is missing. The folder can appear after the startup provider.log.Warn("Failed to provision config", "name", reader.Cfg.Name, "error", err) diff --git a/pkg/services/provisioning/dashboards/dashboard_mock.go b/pkg/services/provisioning/dashboards/dashboard_mock.go index d2cd191fb1c..e665c099b70 100644 --- a/pkg/services/provisioning/dashboards/dashboard_mock.go +++ b/pkg/services/provisioning/dashboards/dashboard_mock.go @@ -13,7 +13,7 @@ type calls struct { // ProvisionerMock is a mock implementation of `Provisioner` type ProvisionerMock struct { Calls *calls - ProvisionFunc func() error + ProvisionFunc func(ctx context.Context) error PollChangesFunc func(ctx context.Context) GetProvisionerResolvedPathFunc func(name string) string GetAllowUIUpdatesFromConfigFunc func(name string) bool @@ -27,10 +27,10 @@ func NewDashboardProvisionerMock() *ProvisionerMock { } // Provision is a mock implementation of `Provisioner.Provision` -func (dpm *ProvisionerMock) Provision() error { +func (dpm *ProvisionerMock) Provision(ctx context.Context) error { dpm.Calls.Provision = append(dpm.Calls.Provision, nil) if dpm.ProvisionFunc != nil { - return dpm.ProvisionFunc() + return dpm.ProvisionFunc(ctx) } return nil } diff --git a/pkg/services/provisioning/dashboards/file_reader.go b/pkg/services/provisioning/dashboards/file_reader.go index 32ac06be608..a612ff84d4d 100644 --- a/pkg/services/provisioning/dashboards/file_reader.go +++ b/pkg/services/provisioning/dashboards/file_reader.go @@ -74,7 +74,7 @@ func (fr *FileReader) pollChanges(ctx context.Context) { for { select { case <-ticker.C: - if err := fr.walkDisk(); err != nil { + if err := fr.walkDisk(ctx); err != nil { fr.log.Error("failed to search for dashboards", "error", err) } case <-ctx.Done(): @@ -85,7 +85,7 @@ func (fr *FileReader) pollChanges(ctx context.Context) { // walkDisk traverses the file system for the defined path, reading dashboard definition files, // and applies any change to the database. -func (fr *FileReader) walkDisk() error { +func (fr *FileReader) walkDisk(ctx context.Context) error { fr.log.Debug("Start walking disk", "path", fr.Path) resolvedPath := fr.resolvedPath() if _, err := os.Stat(resolvedPath); err != nil { @@ -107,9 +107,9 @@ func (fr *FileReader) walkDisk() error { usageTracker := newUsageTracker() if fr.FoldersFromFilesStructure { - err = fr.storeDashboardsInFoldersFromFileStructure(filesFoundOnDisk, provisionedDashboardRefs, resolvedPath, usageTracker) + err = fr.storeDashboardsInFoldersFromFileStructure(ctx, filesFoundOnDisk, provisionedDashboardRefs, resolvedPath, usageTracker) } else { - err = fr.storeDashboardsInFolder(filesFoundOnDisk, provisionedDashboardRefs, usageTracker) + err = fr.storeDashboardsInFolder(ctx, filesFoundOnDisk, provisionedDashboardRefs, usageTracker) } if err != nil { return err @@ -137,9 +137,9 @@ func (fr *FileReader) isDatabaseAccessRestricted() bool { } // storeDashboardsInFolder saves dashboards from the filesystem on disk to the folder from config -func (fr *FileReader) storeDashboardsInFolder(filesFoundOnDisk map[string]os.FileInfo, +func (fr *FileReader) storeDashboardsInFolder(ctx context.Context, filesFoundOnDisk map[string]os.FileInfo, dashboardRefs map[string]*models.DashboardProvisioning, usageTracker *usageTracker) error { - folderID, err := getOrCreateFolderID(fr.Cfg, fr.dashboardProvisioningService, fr.Cfg.Folder) + folderID, err := getOrCreateFolderID(ctx, fr.Cfg, fr.dashboardProvisioningService, fr.Cfg.Folder) if err != nil && !errors.Is(err, ErrFolderNameMissing) { return err } @@ -159,7 +159,7 @@ func (fr *FileReader) storeDashboardsInFolder(filesFoundOnDisk map[string]os.Fil // storeDashboardsInFoldersFromFilesystemStructure saves dashboards from the filesystem on disk to the same folder // in Grafana as they are in on the filesystem. -func (fr *FileReader) storeDashboardsInFoldersFromFileStructure(filesFoundOnDisk map[string]os.FileInfo, +func (fr *FileReader) storeDashboardsInFoldersFromFileStructure(ctx context.Context, filesFoundOnDisk map[string]os.FileInfo, dashboardRefs map[string]*models.DashboardProvisioning, resolvedPath string, usageTracker *usageTracker) error { for path, fileInfo := range filesFoundOnDisk { folderName := "" @@ -169,7 +169,7 @@ func (fr *FileReader) storeDashboardsInFoldersFromFileStructure(filesFoundOnDisk folderName = filepath.Base(dashboardsFolder) } - folderID, err := getOrCreateFolderID(fr.Cfg, fr.dashboardProvisioningService, folderName) + folderID, err := getOrCreateFolderID(ctx, fr.Cfg, fr.dashboardProvisioningService, folderName) if err != nil && !errors.Is(err, ErrFolderNameMissing) { return fmt.Errorf("can't provision folder %q from file system structure: %w", folderName, err) } @@ -291,13 +291,13 @@ func getProvisionedDashboardsByPath(service dashboards.DashboardProvisioningServ return byPath, nil } -func getOrCreateFolderID(cfg *config, service dashboards.DashboardProvisioningService, folderName string) (int64, error) { +func getOrCreateFolderID(ctx context.Context, cfg *config, service dashboards.DashboardProvisioningService, folderName string) (int64, error) { if folderName == "" { return 0, ErrFolderNameMissing } cmd := &models.GetDashboardQuery{Slug: models.SlugifyTitle(folderName), OrgId: cfg.OrgID} - err := bus.Dispatch(cmd) + err := bus.DispatchCtx(ctx, cmd) if err != nil && !errors.Is(err, models.ErrDashboardNotFound) { return 0, err diff --git a/pkg/services/provisioning/dashboards/file_reader_test.go b/pkg/services/provisioning/dashboards/file_reader_test.go index ee3f5f3b339..d6321e8bf69 100644 --- a/pkg/services/provisioning/dashboards/file_reader_test.go +++ b/pkg/services/provisioning/dashboards/file_reader_test.go @@ -1,6 +1,7 @@ package dashboards import ( + "context" "fmt" "math/rand" "os" @@ -115,7 +116,7 @@ func TestDashboardFileReader(t *testing.T) { reader, err := NewDashboardFileReader(cfg, logger, nil) So(err, ShouldBeNil) - err = reader.walkDisk() + err = reader.walkDisk(context.Background()) So(err, ShouldBeNil) folders := 0 @@ -146,7 +147,7 @@ func TestDashboardFileReader(t *testing.T) { reader, err := NewDashboardFileReader(cfg, logger, nil) So(err, ShouldBeNil) - err = reader.walkDisk() + err = reader.walkDisk(context.Background()) So(err, ShouldBeNil) So(len(fakeService.inserted), ShouldEqual, 1) @@ -181,7 +182,7 @@ func TestDashboardFileReader(t *testing.T) { reader, err := NewDashboardFileReader(cfg, logger, nil) So(err, ShouldBeNil) - err = reader.walkDisk() + err = reader.walkDisk(context.Background()) So(err, ShouldBeNil) So(len(fakeService.inserted), ShouldEqual, 0) }) @@ -207,7 +208,7 @@ func TestDashboardFileReader(t *testing.T) { reader, err := NewDashboardFileReader(cfg, logger, nil) So(err, ShouldBeNil) - err = reader.walkDisk() + err = reader.walkDisk(context.Background()) So(err, ShouldBeNil) So(len(fakeService.inserted), ShouldEqual, 1) }) @@ -241,7 +242,7 @@ func TestDashboardFileReader(t *testing.T) { reader, err := NewDashboardFileReader(cfg, logger, nil) So(err, ShouldBeNil) - err = reader.walkDisk() + err = reader.walkDisk(context.Background()) So(err, ShouldBeNil) So(len(fakeService.inserted), ShouldEqual, 0) }) @@ -267,7 +268,7 @@ func TestDashboardFileReader(t *testing.T) { reader, err := NewDashboardFileReader(cfg, logger, nil) So(err, ShouldBeNil) - err = reader.walkDisk() + err = reader.walkDisk(context.Background()) So(err, ShouldBeNil) So(len(fakeService.inserted), ShouldEqual, 1) }) @@ -278,7 +279,7 @@ func TestDashboardFileReader(t *testing.T) { reader, err := NewDashboardFileReader(cfg, logger, nil) So(err, ShouldBeNil) - err = reader.walkDisk() + err = reader.walkDisk(context.Background()) So(err, ShouldBeNil) So(len(fakeService.inserted), ShouldEqual, 1) @@ -291,7 +292,7 @@ func TestDashboardFileReader(t *testing.T) { reader, err := NewDashboardFileReader(cfg, logger, nil) So(err, ShouldBeNil) - err = reader.walkDisk() + err = reader.walkDisk(context.Background()) So(err, ShouldBeNil) So(len(fakeService.inserted), ShouldEqual, 5) @@ -350,13 +351,13 @@ func TestDashboardFileReader(t *testing.T) { reader1, err := NewDashboardFileReader(cfg1, logger, nil) So(err, ShouldBeNil) - err = reader1.walkDisk() + err = reader1.walkDisk(context.Background()) So(err, ShouldBeNil) reader2, err := NewDashboardFileReader(cfg2, logger, nil) So(err, ShouldBeNil) - err = reader2.walkDisk() + err = reader2.walkDisk(context.Background()) So(err, ShouldBeNil) var folderCount int @@ -385,7 +386,7 @@ func TestDashboardFileReader(t *testing.T) { }, } - _, err := getOrCreateFolderID(cfg, fakeService, cfg.Folder) + _, err := getOrCreateFolderID(context.Background(), cfg, fakeService, cfg.Folder) So(err, ShouldEqual, ErrFolderNameMissing) }) @@ -400,7 +401,7 @@ func TestDashboardFileReader(t *testing.T) { }, } - folderID, err := getOrCreateFolderID(cfg, fakeService, cfg.Folder) + folderID, err := getOrCreateFolderID(context.Background(), cfg, fakeService, cfg.Folder) So(err, ShouldBeNil) inserted := false for _, d := range fakeService.inserted { @@ -460,7 +461,7 @@ func TestDashboardFileReader(t *testing.T) { reader, err := NewDashboardFileReader(cfg, logger, nil) So(err, ShouldBeNil) - err = reader.walkDisk() + err = reader.walkDisk(context.Background()) So(err, ShouldBeNil) So(len(fakeService.provisioned["Default"]), ShouldEqual, 1) @@ -471,7 +472,7 @@ func TestDashboardFileReader(t *testing.T) { reader, err := NewDashboardFileReader(cfg, logger, nil) So(err, ShouldBeNil) - err = reader.walkDisk() + err = reader.walkDisk(context.Background()) So(err, ShouldBeNil) So(len(fakeService.provisioned["Default"]), ShouldEqual, 1) diff --git a/pkg/services/provisioning/dashboards/validator_test.go b/pkg/services/provisioning/dashboards/validator_test.go index a170f82cf30..d3bbcdada79 100644 --- a/pkg/services/provisioning/dashboards/validator_test.go +++ b/pkg/services/provisioning/dashboards/validator_test.go @@ -1,6 +1,7 @@ package dashboards import ( + "context" "sort" "testing" @@ -31,7 +32,7 @@ func TestDuplicatesValidator(t *testing.T) { t.Run("Duplicates validator should collect info about duplicate UIDs and titles within folders", func(t *testing.T) { const folderName = "duplicates-validator-folder" - folderID, err := getOrCreateFolderID(cfg, fakeService, folderName) + folderID, err := getOrCreateFolderID(context.Background(), cfg, fakeService, folderName) require.NoError(t, err) identity := dashboardIdentity{folderID: folderID, title: "Grafana"} @@ -53,10 +54,10 @@ func TestDuplicatesValidator(t *testing.T) { duplicateValidator := newDuplicateValidator(logger, []*FileReader{reader1, reader2}) - err = reader1.walkDisk() + err = reader1.walkDisk(context.Background()) require.NoError(t, err) - err = reader2.walkDisk() + err = reader2.walkDisk(context.Background()) require.NoError(t, err) duplicates := duplicateValidator.getDuplicates() @@ -94,15 +95,15 @@ func TestDuplicatesValidator(t *testing.T) { duplicateValidator := newDuplicateValidator(logger, []*FileReader{reader1, reader2}) - err = reader1.walkDisk() + err = reader1.walkDisk(context.Background()) require.NoError(t, err) - err = reader2.walkDisk() + err = reader2.walkDisk(context.Background()) require.NoError(t, err) duplicates := duplicateValidator.getDuplicates() - folderID, err := getOrCreateFolderID(cfg, fakeService, cfg1.Folder) + folderID, err := getOrCreateFolderID(context.Background(), cfg, fakeService, cfg1.Folder) require.NoError(t, err) identity := dashboardIdentity{folderID: folderID, title: "Grafana"} diff --git a/pkg/services/provisioning/provisioning.go b/pkg/services/provisioning/provisioning.go index df0fa51b8aa..236c3bea330 100644 --- a/pkg/services/provisioning/provisioning.go +++ b/pkg/services/provisioning/provisioning.go @@ -163,7 +163,7 @@ func (ps *ProvisioningServiceImpl) ProvisionDashboards() error { ps.cancelPolling() dashProvisioner.CleanUpOrphanedDashboards() - err = dashProvisioner.Provision() + err = dashProvisioner.Provision(context.TODO()) if err != nil { // If we fail to provision with the new provisioner, the mutex will unlock and the polling will restart with the // old provisioner as we did not switch them yet. diff --git a/pkg/services/provisioning/provisioning_test.go b/pkg/services/provisioning/provisioning_test.go index 9979b47d6e8..a410ec5a180 100644 --- a/pkg/services/provisioning/provisioning_test.go +++ b/pkg/services/provisioning/provisioning_test.go @@ -48,7 +48,7 @@ func TestProvisioningServiceImpl(t *testing.T) { serviceTest.waitForPollChanges() assert.Equal(t, 1, len(serviceTest.mock.Calls.PollChanges), "PollChanges should have been called") - serviceTest.mock.ProvisionFunc = func() error { + serviceTest.mock.ProvisionFunc = func(ctx context.Context) error { return errors.New("Test error") } err = serviceTest.service.ProvisionDashboards() diff --git a/pkg/services/sqlstore/dashboard.go b/pkg/services/sqlstore/dashboard.go index e508cadce0d..621ba2408e9 100644 --- a/pkg/services/sqlstore/dashboard.go +++ b/pkg/services/sqlstore/dashboard.go @@ -234,7 +234,7 @@ func (ss *SQLStore) GetFolderByTitle(orgID int64, title string) (*models.Dashboa // TODO: Remove me func GetDashboard(query *models.GetDashboardQuery) error { - return GetDashboardCtx(context.Background(), query) + return GetDashboardCtx(context.TODO(), query) } func GetDashboardCtx(ctx context.Context, query *models.GetDashboardQuery) error { diff --git a/pkg/services/sqlstore/dashboard_test.go b/pkg/services/sqlstore/dashboard_test.go index bd46251c4ed..fbcdeba190e 100644 --- a/pkg/services/sqlstore/dashboard_test.go +++ b/pkg/services/sqlstore/dashboard_test.go @@ -56,7 +56,7 @@ func TestDashboardDataAccess(t *testing.T) { OrgId: 1, } - err := GetDashboard(&query) + err := GetDashboardCtx(context.Background(), &query) So(err, ShouldBeNil) So(query.Result.Title, ShouldEqual, "test dash 23") @@ -72,7 +72,7 @@ func TestDashboardDataAccess(t *testing.T) { OrgId: 1, } - err := GetDashboard(&query) + err := GetDashboardCtx(context.Background(), &query) So(err, ShouldBeNil) So(query.Result.Title, ShouldEqual, "test dash 23") @@ -88,7 +88,7 @@ func TestDashboardDataAccess(t *testing.T) { OrgId: 1, } - err := GetDashboard(&query) + err := GetDashboardCtx(context.Background(), &query) So(err, ShouldBeNil) So(query.Result.Title, ShouldEqual, "test dash 23") @@ -103,7 +103,7 @@ func TestDashboardDataAccess(t *testing.T) { OrgId: 1, } - err := GetDashboard(&query) + err := GetDashboardCtx(context.Background(), &query) So(err, ShouldEqual, models.ErrDashboardIdentifierNotSet) }) @@ -191,7 +191,7 @@ func TestDashboardDataAccess(t *testing.T) { OrgId: 1, } - err = GetDashboard(&query) + err = GetDashboardCtx(context.Background(), &query) So(err, ShouldBeNil) So(query.Result.FolderId, ShouldEqual, 0) So(query.Result.CreatedBy, ShouldEqual, savedDash.CreatedBy) diff --git a/pkg/services/sqlstore/dashboard_version_test.go b/pkg/services/sqlstore/dashboard_version_test.go index 233772581da..c88eabe32f8 100644 --- a/pkg/services/sqlstore/dashboard_version_test.go +++ b/pkg/services/sqlstore/dashboard_version_test.go @@ -4,6 +4,7 @@ package sqlstore import ( + "context" "reflect" "testing" @@ -51,7 +52,7 @@ func TestGetDashboardVersion(t *testing.T) { Uid: savedDash.Uid, } - err = GetDashboard(&dashCmd) + err = GetDashboardCtx(context.Background(), &dashCmd) So(err, ShouldBeNil) eq := reflect.DeepEqual(dashCmd.Result.Data, query.Result.Data) So(eq, ShouldEqual, true)