From 47f6bb3583f701ff61c209ea1166a54d293ddce7 Mon Sep 17 00:00:00 2001 From: idafurjes <36131195+idafurjes@users.noreply.github.com> Date: Wed, 3 Nov 2021 11:31:56 +0100 Subject: [PATCH] Chore: Add context to org (#40685) * Add context to org * Rebase * Fix rebase --- pkg/api/admin_provisioning.go | 2 +- pkg/api/admin_provisioning_test.go | 3 +- pkg/api/dashboard_test.go | 10 +++--- pkg/api/org.go | 32 +++++++++--------- pkg/services/live/live.go | 2 +- .../provisioning/dashboards/config_reader.go | 5 +-- .../dashboards/config_reader_test.go | 15 +++++---- .../provisioning/dashboards/dashboard.go | 6 ++-- .../provisioning/datasources/config_reader.go | 13 ++++---- .../datasources/config_reader_test.go | 10 +++--- .../provisioning/datasources/datasources.go | 2 +- .../notifiers/alert_notifications.go | 9 ++--- .../provisioning/notifiers/config_reader.go | 8 ++--- .../notifiers/config_reader_test.go | 33 ++++++++++--------- pkg/services/provisioning/provisioning.go | 14 ++++---- .../provisioning/provisioning_mock.go | 4 +-- .../provisioning/provisioning_test.go | 2 +- pkg/services/provisioning/utils/utils.go | 5 +-- pkg/services/provisioning/utils/utils_test.go | 7 ++-- pkg/services/sqlstore/org.go | 28 ++++++++-------- pkg/services/sqlstore/org_test.go | 14 ++++---- pkg/services/sqlstore/quota_test.go | 2 +- pkg/services/sqlstore/stats_test.go | 4 +-- pkg/services/sqlstore/user_test.go | 2 +- 24 files changed, 120 insertions(+), 112 deletions(-) diff --git a/pkg/api/admin_provisioning.go b/pkg/api/admin_provisioning.go index 43598973635..594903d8b0c 100644 --- a/pkg/api/admin_provisioning.go +++ b/pkg/api/admin_provisioning.go @@ -33,7 +33,7 @@ func (hs *HTTPServer) AdminProvisioningReloadPlugins(c *models.ReqContext) respo } func (hs *HTTPServer) AdminProvisioningReloadNotifications(c *models.ReqContext) response.Response { - err := hs.ProvisioningService.ProvisionNotifications() + err := hs.ProvisioningService.ProvisionNotifications(c.Req.Context()) if err != nil { return response.Error(500, "", err) } diff --git a/pkg/api/admin_provisioning_test.go b/pkg/api/admin_provisioning_test.go index da55d7ca05f..19db83329b3 100644 --- a/pkg/api/admin_provisioning_test.go +++ b/pkg/api/admin_provisioning_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "net/http" "net/http/httptest" "testing" @@ -143,7 +144,7 @@ func TestAPI_AdminProvisioningReload_AccessControl(t *testing.T) { sc, hs := setupAccessControlScenarioContext(t, cfg, test.url, test.permissions) // Setup the mock - provisioningMock := provisioning.NewProvisioningServiceMock() + provisioningMock := provisioning.NewProvisioningServiceMock(context.Background()) hs.ProvisioningService = provisioningMock sc.resp = httptest.NewRecorder() diff --git a/pkg/api/dashboard_test.go b/pkg/api/dashboard_test.go index 724158a61b5..4b3000eac1e 100644 --- a/pkg/api/dashboard_test.go +++ b/pkg/api/dashboard_test.go @@ -972,7 +972,7 @@ func TestDashboardAPIEndpoint(t *testing.T) { loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/uid/dash", "/api/dashboards/uid/:uid", models.ROLE_EDITOR, func(sc *scenarioContext) { setUp() - mock := provisioning.NewProvisioningServiceMock() + mock := provisioning.NewProvisioningServiceMock(context.Background()) mock.GetDashboardProvisionerResolvedPathFunc = func(name string) string { return "/tmp/grafana/dashboards" } @@ -985,7 +985,7 @@ func TestDashboardAPIEndpoint(t *testing.T) { loggedInUserScenarioWithRole(t, "When allowUiUpdates is true and calling GET on", "GET", "/api/dashboards/uid/dash", "/api/dashboards/uid/:uid", models.ROLE_EDITOR, func(sc *scenarioContext) { setUp() - mock := provisioning.NewProvisioningServiceMock() + mock := provisioning.NewProvisioningServiceMock(context.Background()) mock.GetDashboardProvisionerResolvedPathFunc = func(name string) string { return "/tmp/grafana/dashboards" } @@ -1015,7 +1015,7 @@ func TestDashboardAPIEndpoint(t *testing.T) { func getDashboardShouldReturn200WithConfig(sc *scenarioContext, provisioningService provisioning.ProvisioningService) dtos. DashboardFullWithMeta { if provisioningService == nil { - provisioningService = provisioning.NewProvisioningServiceMock() + provisioningService = provisioning.NewProvisioningServiceMock(context.Background()) } libraryPanelsService := mockLibraryPanelService{} @@ -1110,7 +1110,7 @@ func postDashboardScenario(t *testing.T, desc string, url string, routePattern s hs := HTTPServer{ Bus: bus.GetBus(), Cfg: cfg, - ProvisioningService: provisioning.NewProvisioningServiceMock(), + ProvisioningService: provisioning.NewProvisioningServiceMock(context.Background()), Live: newTestLive(t), QuotaService: "a.QuotaService{ Cfg: cfg, @@ -1179,7 +1179,7 @@ func restoreDashboardVersionScenario(t *testing.T, desc string, url string, rout hs := HTTPServer{ Cfg: cfg, Bus: bus.GetBus(), - ProvisioningService: provisioning.NewProvisioningServiceMock(), + ProvisioningService: provisioning.NewProvisioningServiceMock(context.Background()), Live: newTestLive(t), QuotaService: "a.QuotaService{Cfg: cfg}, LibraryPanelService: &mockLibraryPanelService{}, diff --git a/pkg/api/org.go b/pkg/api/org.go index 5f99d564fb7..4bffc06c709 100644 --- a/pkg/api/org.go +++ b/pkg/api/org.go @@ -1,6 +1,7 @@ package api import ( + "context" "errors" "github.com/grafana/grafana/pkg/api/dtos" @@ -15,12 +16,12 @@ import ( // GET /api/org func GetCurrentOrg(c *models.ReqContext) response.Response { - return getOrgHelper(c.OrgId) + return getOrgHelper(c.Req.Context(), c.OrgId) } // GET /api/orgs/:orgId func GetOrgByID(c *models.ReqContext) response.Response { - return getOrgHelper(c.ParamsInt64(":orgId")) + return getOrgHelper(c.Req.Context(), c.ParamsInt64(":orgId")) } // Get /api/orgs/name/:name @@ -49,14 +50,13 @@ func (hs *HTTPServer) GetOrgByName(c *models.ReqContext) response.Response { return response.JSON(200, &result) } -func getOrgHelper(orgID int64) response.Response { +func getOrgHelper(ctx context.Context, orgID int64) response.Response { query := models.GetOrgByIdQuery{Id: orgID} - if err := sqlstore.GetOrgById(&query); err != nil { + if err := sqlstore.GetOrgById(ctx, &query); err != nil { if errors.Is(err, models.ErrOrgNotFound) { return response.Error(404, "Organization not found", err) } - return response.Error(500, "Failed to get organization", err) } @@ -85,7 +85,7 @@ func (hs *HTTPServer) CreateOrg(c *models.ReqContext, cmd models.CreateOrgComman } cmd.UserId = c.UserId - if err := sqlstore.CreateOrg(&cmd); err != nil { + if err := sqlstore.CreateOrg(c.Req.Context(), &cmd); err != nil { if errors.Is(err, models.ErrOrgNameTaken) { return response.Error(409, "Organization name taken", err) } @@ -102,17 +102,17 @@ func (hs *HTTPServer) CreateOrg(c *models.ReqContext, cmd models.CreateOrgComman // PUT /api/org func UpdateCurrentOrg(c *models.ReqContext, form dtos.UpdateOrgForm) response.Response { - return updateOrgHelper(form, c.OrgId) + return updateOrgHelper(c.Req.Context(), form, c.OrgId) } // PUT /api/orgs/:orgId func UpdateOrg(c *models.ReqContext, form dtos.UpdateOrgForm) response.Response { - return updateOrgHelper(form, c.ParamsInt64(":orgId")) + return updateOrgHelper(c.Req.Context(), form, c.ParamsInt64(":orgId")) } -func updateOrgHelper(form dtos.UpdateOrgForm, orgID int64) response.Response { +func updateOrgHelper(ctx context.Context, form dtos.UpdateOrgForm, orgID int64) response.Response { cmd := models.UpdateOrgCommand{Name: form.Name, OrgId: orgID} - if err := sqlstore.UpdateOrg(&cmd); err != nil { + if err := sqlstore.UpdateOrg(ctx, &cmd); err != nil { if errors.Is(err, models.ErrOrgNameTaken) { return response.Error(400, "Organization name taken", err) } @@ -124,15 +124,15 @@ func updateOrgHelper(form dtos.UpdateOrgForm, orgID int64) response.Response { // PUT /api/org/address func UpdateCurrentOrgAddress(c *models.ReqContext, form dtos.UpdateOrgAddressForm) response.Response { - return updateOrgAddressHelper(form, c.OrgId) + return updateOrgAddressHelper(c.Req.Context(), form, c.OrgId) } // PUT /api/orgs/:orgId/address func UpdateOrgAddress(c *models.ReqContext, form dtos.UpdateOrgAddressForm) response.Response { - return updateOrgAddressHelper(form, c.ParamsInt64(":orgId")) + return updateOrgAddressHelper(c.Req.Context(), form, c.ParamsInt64(":orgId")) } -func updateOrgAddressHelper(form dtos.UpdateOrgAddressForm, orgID int64) response.Response { +func updateOrgAddressHelper(ctx context.Context, form dtos.UpdateOrgAddressForm, orgID int64) response.Response { cmd := models.UpdateOrgAddressCommand{ OrgId: orgID, Address: models.Address{ @@ -145,7 +145,7 @@ func updateOrgAddressHelper(form dtos.UpdateOrgAddressForm, orgID int64) respons }, } - if err := sqlstore.UpdateOrgAddress(&cmd); err != nil { + if err := sqlstore.UpdateOrgAddress(ctx, &cmd); err != nil { return response.Error(500, "Failed to update org address", err) } @@ -160,7 +160,7 @@ func DeleteOrgByID(c *models.ReqContext) response.Response { return response.Error(400, "Can not delete org for current user", nil) } - if err := sqlstore.DeleteOrg(&models.DeleteOrgCommand{Id: orgID}); err != nil { + if err := sqlstore.DeleteOrg(c.Req.Context(), &models.DeleteOrgCommand{Id: orgID}); err != nil { if errors.Is(err, models.ErrOrgNotFound) { return response.Error(404, "Failed to delete organization. ID not found", nil) } @@ -184,7 +184,7 @@ func SearchOrgs(c *models.ReqContext) response.Response { Limit: perPage, } - if err := sqlstore.SearchOrgs(&query); err != nil { + if err := sqlstore.SearchOrgs(c.Req.Context(), &query); err != nil { return response.Error(500, "Failed to search orgs", err) } diff --git a/pkg/services/live/live.go b/pkg/services/live/live.go index 91767a8601e..b6e5c82db62 100644 --- a/pkg/services/live/live.go +++ b/pkg/services/live/live.go @@ -197,7 +197,7 @@ func ProvideService(plugCtxProvider *plugincontext.Provider, cfg *setting.Cfg, r // This can be unreasonable to have in production scenario with many // organizations. query := &models.SearchOrgsQuery{} - err := sqlstore.SearchOrgs(query) + err := sqlstore.SearchOrgs(context.TODO(), query) if err != nil { return nil, fmt.Errorf("can't get org list: %w", err) } diff --git a/pkg/services/provisioning/dashboards/config_reader.go b/pkg/services/provisioning/dashboards/config_reader.go index ca469cecf2e..d6dc0c3a2cc 100644 --- a/pkg/services/provisioning/dashboards/config_reader.go +++ b/pkg/services/provisioning/dashboards/config_reader.go @@ -1,6 +1,7 @@ package dashboards import ( + "context" "fmt" "io/ioutil" "os" @@ -62,7 +63,7 @@ func (cr *configReader) parseConfigs(file os.FileInfo) ([]*config, error) { return []*config{}, nil } -func (cr *configReader) readConfig() ([]*config, error) { +func (cr *configReader) readConfig(ctx context.Context) ([]*config, error) { var dashboards []*config files, err := ioutil.ReadDir(cr.path) @@ -92,7 +93,7 @@ func (cr *configReader) readConfig() ([]*config, error) { dashboard.OrgID = 1 } - if err := utils.CheckOrgExists(dashboard.OrgID); err != nil { + if err := utils.CheckOrgExists(ctx, dashboard.OrgID); err != nil { return nil, fmt.Errorf("failed to provision dashboards with %q reader: %w", dashboard.Name, err) } diff --git a/pkg/services/provisioning/dashboards/config_reader_test.go b/pkg/services/provisioning/dashboards/config_reader_test.go index 8a76b815056..1af40e82853 100644 --- a/pkg/services/provisioning/dashboards/config_reader_test.go +++ b/pkg/services/provisioning/dashboards/config_reader_test.go @@ -1,6 +1,7 @@ package dashboards import ( + "context" "errors" "fmt" "os" @@ -28,20 +29,20 @@ func TestDashboardsAsConfig(t *testing.T) { t.Run("Should fail if orgs don't exist in the database", func(t *testing.T) { cfgProvider := configReader{path: appliedDefaults, log: logger} - _, err := cfgProvider.readConfig() + _, err := cfgProvider.readConfig(context.Background()) require.Error(t, err) assert.True(t, errors.Is(err, models.ErrOrgNotFound)) }) for i := 1; i <= 2; i++ { orgCommand := models.CreateOrgCommand{Name: fmt.Sprintf("Main Org. %v", i)} - err := sqlstore.CreateOrg(&orgCommand) + err := sqlstore.CreateOrg(context.Background(), &orgCommand) require.NoError(t, err) } t.Run("default values should be applied", func(t *testing.T) { cfgProvider := configReader{path: appliedDefaults, log: logger} - cfg, err := cfgProvider.readConfig() + cfg, err := cfgProvider.readConfig(context.Background()) require.NoError(t, err) require.Equal(t, "file", cfg[0].Type) @@ -52,7 +53,7 @@ func TestDashboardsAsConfig(t *testing.T) { t.Run("Can read config file version 1 format", func(t *testing.T) { _ = os.Setenv("TEST_VAR", "general") cfgProvider := configReader{path: simpleDashboardConfig, log: logger} - cfg, err := cfgProvider.readConfig() + cfg, err := cfgProvider.readConfig(context.Background()) _ = os.Unsetenv("TEST_VAR") require.NoError(t, err) @@ -61,7 +62,7 @@ func TestDashboardsAsConfig(t *testing.T) { t.Run("Can read config file in version 0 format", func(t *testing.T) { cfgProvider := configReader{path: oldVersion, log: logger} - cfg, err := cfgProvider.readConfig() + cfg, err := cfgProvider.readConfig(context.Background()) require.NoError(t, err) validateDashboardAsConfig(t, cfg) @@ -69,7 +70,7 @@ func TestDashboardsAsConfig(t *testing.T) { t.Run("Should skip invalid path", func(t *testing.T) { cfgProvider := configReader{path: "/invalid-directory", log: logger} - cfg, err := cfgProvider.readConfig() + cfg, err := cfgProvider.readConfig(context.Background()) if err != nil { t.Fatalf("readConfig return an error %v", err) } @@ -79,7 +80,7 @@ func TestDashboardsAsConfig(t *testing.T) { t.Run("Should skip broken config files", func(t *testing.T) { cfgProvider := configReader{path: brokenConfigs, log: logger} - cfg, err := cfgProvider.readConfig() + cfg, err := cfgProvider.readConfig(context.Background()) if err != nil { t.Fatalf("readConfig return an error %v", err) } diff --git a/pkg/services/provisioning/dashboards/dashboard.go b/pkg/services/provisioning/dashboards/dashboard.go index 5bbca319d5e..44f194a9d40 100644 --- a/pkg/services/provisioning/dashboards/dashboard.go +++ b/pkg/services/provisioning/dashboards/dashboard.go @@ -23,7 +23,7 @@ type DashboardProvisioner interface { } // DashboardProvisionerFactory creates DashboardProvisioners based on input -type DashboardProvisionerFactory func(string, dashboards.Store) (DashboardProvisioner, error) +type DashboardProvisionerFactory func(context.Context, string, dashboards.Store) (DashboardProvisioner, error) // Provisioner is responsible for syncing dashboard from disk to Grafana's database. type Provisioner struct { @@ -34,10 +34,10 @@ type Provisioner struct { } // New returns a new DashboardProvisioner -func New(configDirectory string, store dashboards.Store) (DashboardProvisioner, error) { +func New(ctx context.Context, configDirectory string, store dashboards.Store) (DashboardProvisioner, error) { logger := log.New("provisioning.dashboard") cfgReader := &configReader{path: configDirectory, log: logger} - configs, err := cfgReader.readConfig() + configs, err := cfgReader.readConfig(ctx) if err != nil { return nil, errutil.Wrap("Failed to read dashboards config", err) } diff --git a/pkg/services/provisioning/datasources/config_reader.go b/pkg/services/provisioning/datasources/config_reader.go index 191ab962342..4e40010d220 100644 --- a/pkg/services/provisioning/datasources/config_reader.go +++ b/pkg/services/provisioning/datasources/config_reader.go @@ -1,6 +1,7 @@ package datasources import ( + "context" "fmt" "io/ioutil" "os" @@ -17,7 +18,7 @@ type configReader struct { log log.Logger } -func (cr *configReader) readConfig(path string) ([]*configs, error) { +func (cr *configReader) readConfig(ctx context.Context, path string) ([]*configs, error) { var datasources []*configs files, err := ioutil.ReadDir(path) @@ -39,7 +40,7 @@ func (cr *configReader) readConfig(path string) ([]*configs, error) { } } - err = cr.validateDefaultUniqueness(datasources) + err = cr.validateDefaultUniqueness(ctx, datasources) if err != nil { return nil, err } @@ -88,7 +89,7 @@ func (cr *configReader) parseDatasourceConfig(path string, file os.FileInfo) (*c return v0.mapToDatasourceFromConfig(apiVersion.APIVersion), nil } -func (cr *configReader) validateDefaultUniqueness(datasources []*configs) error { +func (cr *configReader) validateDefaultUniqueness(ctx context.Context, datasources []*configs) error { defaultCount := map[int64]int{} for i := range datasources { if datasources[i].Datasources == nil { @@ -100,7 +101,7 @@ func (cr *configReader) validateDefaultUniqueness(datasources []*configs) error ds.OrgID = 1 } - if err := cr.validateAccessAndOrgID(ds); err != nil { + if err := cr.validateAccessAndOrgID(ctx, ds); err != nil { return fmt.Errorf("failed to provision %q data source: %w", ds.Name, err) } @@ -122,8 +123,8 @@ func (cr *configReader) validateDefaultUniqueness(datasources []*configs) error return nil } -func (cr *configReader) validateAccessAndOrgID(ds *upsertDataSourceFromConfig) error { - if err := utils.CheckOrgExists(ds.OrgID); err != nil { +func (cr *configReader) validateAccessAndOrgID(ctx context.Context, ds *upsertDataSourceFromConfig) error { + if err := utils.CheckOrgExists(ctx, ds.OrgID); err != nil { return err } diff --git a/pkg/services/provisioning/datasources/config_reader_test.go b/pkg/services/provisioning/datasources/config_reader_test.go index 8446c271c41..782d502c22d 100644 --- a/pkg/services/provisioning/datasources/config_reader_test.go +++ b/pkg/services/provisioning/datasources/config_reader_test.go @@ -151,20 +151,20 @@ func TestDatasourceAsConfig(t *testing.T) { t.Run("broken yaml should return error", func(t *testing.T) { reader := &configReader{} - _, err := reader.readConfig(brokenYaml) + _, err := reader.readConfig(context.Background(), brokenYaml) require.NotNil(t, err) }) t.Run("invalid access should warn about invalid value and return 'proxy'", func(t *testing.T) { reader := &configReader{log: logger} - configs, err := reader.readConfig(invalidAccess) + configs, err := reader.readConfig(context.Background(), invalidAccess) require.NoError(t, err) require.Equal(t, configs[0].Datasources[0].Access, models.DS_ACCESS_PROXY) }) t.Run("skip invalid directory", func(t *testing.T) { cfgProvider := &configReader{log: log.New("test logger")} - cfg, err := cfgProvider.readConfig("./invalid-directory") + cfg, err := cfgProvider.readConfig(context.Background(), "./invalid-directory") if err != nil { t.Fatalf("readConfig return an error %v", err) } @@ -175,7 +175,7 @@ func TestDatasourceAsConfig(t *testing.T) { t.Run("can read all properties from version 1", func(t *testing.T) { _ = os.Setenv("TEST_VAR", "name") cfgProvider := &configReader{log: log.New("test logger")} - cfg, err := cfgProvider.readConfig(allProperties) + cfg, err := cfgProvider.readConfig(context.Background(), allProperties) _ = os.Unsetenv("TEST_VAR") if err != nil { t.Fatalf("readConfig return an error %v", err) @@ -204,7 +204,7 @@ func TestDatasourceAsConfig(t *testing.T) { t.Run("can read all properties from version 0", func(t *testing.T) { cfgProvider := &configReader{log: log.New("test logger")} - cfg, err := cfgProvider.readConfig(versionZero) + cfg, err := cfgProvider.readConfig(context.Background(), versionZero) if err != nil { t.Fatalf("readConfig return an error %v", err) } diff --git a/pkg/services/provisioning/datasources/datasources.go b/pkg/services/provisioning/datasources/datasources.go index 9d2db2c451b..3e28980778d 100644 --- a/pkg/services/provisioning/datasources/datasources.go +++ b/pkg/services/provisioning/datasources/datasources.go @@ -69,7 +69,7 @@ func (dc *DatasourceProvisioner) apply(ctx context.Context, cfg *configs) error } func (dc *DatasourceProvisioner) applyChanges(ctx context.Context, configPath string) error { - configs, err := dc.cfgProvider.readConfig(configPath) + configs, err := dc.cfgProvider.readConfig(ctx, configPath) if err != nil { return err } diff --git a/pkg/services/provisioning/notifiers/alert_notifications.go b/pkg/services/provisioning/notifiers/alert_notifications.go index 153f10ce5a9..03f23ae0523 100644 --- a/pkg/services/provisioning/notifiers/alert_notifications.go +++ b/pkg/services/provisioning/notifiers/alert_notifications.go @@ -5,12 +5,13 @@ import ( "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/encryption" + "golang.org/x/net/context" ) // Provision alert notifiers -func Provision(configDirectory string, encryptionService encryption.Service) error { +func Provision(ctx context.Context, configDirectory string, encryptionService encryption.Service) error { dc := newNotificationProvisioner(encryptionService, log.New("provisioning.notifiers")) - return dc.applyChanges(configDirectory) + return dc.applyChanges(ctx, configDirectory) } // NotificationProvisioner is responsible for provsioning alert notifiers @@ -132,8 +133,8 @@ func (dc *NotificationProvisioner) mergeNotifications(notificationToMerge []*not return nil } -func (dc *NotificationProvisioner) applyChanges(configPath string) error { - configs, err := dc.cfgProvider.readConfig(configPath) +func (dc *NotificationProvisioner) applyChanges(ctx context.Context, configPath string) error { + configs, err := dc.cfgProvider.readConfig(ctx, configPath) if err != nil { return err } diff --git a/pkg/services/provisioning/notifiers/config_reader.go b/pkg/services/provisioning/notifiers/config_reader.go index 5095401269d..98bd117e447 100644 --- a/pkg/services/provisioning/notifiers/config_reader.go +++ b/pkg/services/provisioning/notifiers/config_reader.go @@ -22,7 +22,7 @@ type configReader struct { log log.Logger } -func (cr *configReader) readConfig(path string) ([]*notificationsAsConfig, error) { +func (cr *configReader) readConfig(ctx context.Context, path string) ([]*notificationsAsConfig, error) { var notifications []*notificationsAsConfig cr.log.Debug("Looking for alert notification provisioning files", "path", path) @@ -51,7 +51,7 @@ func (cr *configReader) readConfig(path string) ([]*notificationsAsConfig, error return nil, err } - if err := cr.checkOrgIDAndOrgName(notifications); err != nil { + if err := cr.checkOrgIDAndOrgName(ctx, notifications); err != nil { return nil, err } @@ -81,7 +81,7 @@ func (cr *configReader) parseNotificationConfig(path string, file os.FileInfo) ( return cfg.mapToNotificationFromConfig(), nil } -func (cr *configReader) checkOrgIDAndOrgName(notifications []*notificationsAsConfig) error { +func (cr *configReader) checkOrgIDAndOrgName(ctx context.Context, notifications []*notificationsAsConfig) error { for i := range notifications { for _, notification := range notifications[i].Notifications { if notification.OrgID < 1 { @@ -91,7 +91,7 @@ func (cr *configReader) checkOrgIDAndOrgName(notifications []*notificationsAsCon notification.OrgID = 0 } } else { - if err := utils.CheckOrgExists(notification.OrgID); err != nil { + if err := utils.CheckOrgExists(ctx, notification.OrgID); err != nil { return fmt.Errorf("failed to provision %q notification: %w", notification.Name, err) } } diff --git a/pkg/services/provisioning/notifiers/config_reader_test.go b/pkg/services/provisioning/notifiers/config_reader_test.go index eefe6ce53ef..e768d690ade 100644 --- a/pkg/services/provisioning/notifiers/config_reader_test.go +++ b/pkg/services/provisioning/notifiers/config_reader_test.go @@ -1,6 +1,7 @@ package notifiers import ( + "context" "fmt" "os" "testing" @@ -40,7 +41,7 @@ func TestNotificationAsConfig(t *testing.T) { for i := 1; i < 5; i++ { orgCommand := models.CreateOrgCommand{Name: fmt.Sprintf("Main Org. %v", i)} - err := sqlstore.CreateOrg(&orgCommand) + err := sqlstore.CreateOrg(context.Background(), &orgCommand) require.NoError(t, err) } @@ -65,7 +66,7 @@ func TestNotificationAsConfig(t *testing.T) { log: log.New("test logger"), } - cfg, err := cfgProvider.readConfig(correctProperties) + cfg, err := cfgProvider.readConfig(context.Background(), correctProperties) _ = os.Unsetenv("TEST_VAR") if err != nil { t.Fatalf("readConfig return an error %v", err) @@ -140,7 +141,7 @@ func TestNotificationAsConfig(t *testing.T) { setup() dc := newNotificationProvisioner(ossencryption.ProvideService(), logger) - err := dc.applyChanges(twoNotificationsConfig) + err := dc.applyChanges(context.Background(), twoNotificationsConfig) if err != nil { t.Fatalf("applyChanges return an error %v", err) } @@ -170,7 +171,7 @@ func TestNotificationAsConfig(t *testing.T) { t.Run("should update one notification", func(t *testing.T) { dc := newNotificationProvisioner(ossencryption.ProvideService(), logger) - err = dc.applyChanges(twoNotificationsConfig) + err = dc.applyChanges(context.Background(), twoNotificationsConfig) if err != nil { t.Fatalf("applyChanges return an error %v", err) } @@ -194,7 +195,7 @@ func TestNotificationAsConfig(t *testing.T) { t.Run("Two notifications with is_default", func(t *testing.T) { setup() dc := newNotificationProvisioner(ossencryption.ProvideService(), logger) - err := dc.applyChanges(doubleNotificationsConfig) + err := dc.applyChanges(context.Background(), doubleNotificationsConfig) t.Run("should both be inserted", func(t *testing.T) { require.NoError(t, err) notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1} @@ -237,7 +238,7 @@ func TestNotificationAsConfig(t *testing.T) { t.Run("should have two new notifications", func(t *testing.T) { dc := newNotificationProvisioner(ossencryption.ProvideService(), logger) - err := dc.applyChanges(twoNotificationsConfig) + err := dc.applyChanges(context.Background(), twoNotificationsConfig) if err != nil { t.Fatalf("applyChanges return an error %v", err) } @@ -253,11 +254,11 @@ func TestNotificationAsConfig(t *testing.T) { t.Run("Can read correct properties with orgName instead of orgId", func(t *testing.T) { setup() existingOrg1 := models.GetOrgByNameQuery{Name: "Main Org. 1"} - err := sqlstore.GetOrgByName(&existingOrg1) + err := sqlstore.GetOrgByName(context.Background(), &existingOrg1) require.NoError(t, err) require.NotNil(t, existingOrg1.Result) existingOrg2 := models.GetOrgByNameQuery{Name: "Main Org. 2"} - err = sqlstore.GetOrgByName(&existingOrg2) + err = sqlstore.GetOrgByName(context.Background(), &existingOrg2) require.NoError(t, err) require.NotNil(t, existingOrg2.Result) @@ -271,7 +272,7 @@ func TestNotificationAsConfig(t *testing.T) { require.NoError(t, err) dc := newNotificationProvisioner(ossencryption.ProvideService(), logger) - err = dc.applyChanges(correctPropertiesWithOrgName) + err = dc.applyChanges(context.Background(), correctPropertiesWithOrgName) if err != nil { t.Fatalf("applyChanges return an error %v", err) } @@ -290,7 +291,7 @@ func TestNotificationAsConfig(t *testing.T) { t.Run("Config doesn't contain required field", func(t *testing.T) { setup() dc := newNotificationProvisioner(ossencryption.ProvideService(), logger) - err := dc.applyChanges(noRequiredFields) + err := dc.applyChanges(context.Background(), noRequiredFields) require.NotNil(t, err) errString := err.Error() @@ -304,7 +305,7 @@ func TestNotificationAsConfig(t *testing.T) { t.Run("should have not changed repo", func(t *testing.T) { setup() dc := newNotificationProvisioner(ossencryption.ProvideService(), logger) - err := dc.applyChanges(emptyFile) + err := dc.applyChanges(context.Background(), emptyFile) if err != nil { t.Fatalf("applyChanges return an error %v", err) } @@ -321,7 +322,7 @@ func TestNotificationAsConfig(t *testing.T) { log: log.New("test logger"), } - _, err := reader.readConfig(brokenYaml) + _, err := reader.readConfig(context.Background(), brokenYaml) require.NotNil(t, err) }) @@ -331,7 +332,7 @@ func TestNotificationAsConfig(t *testing.T) { log: log.New("test logger"), } - cfg, err := cfgProvider.readConfig(emptyFolder) + cfg, err := cfgProvider.readConfig(context.Background(), emptyFolder) if err != nil { t.Fatalf("readConfig return an error %v", err) } @@ -343,7 +344,7 @@ func TestNotificationAsConfig(t *testing.T) { encryptionService: ossencryption.ProvideService(), log: log.New("test logger"), } - _, err := cfgProvider.readConfig(unknownNotifier) + _, err := cfgProvider.readConfig(context.Background(), unknownNotifier) require.NotNil(t, err) require.Equal(t, err.Error(), `unsupported notification type "nonexisting"`) }) @@ -353,7 +354,7 @@ func TestNotificationAsConfig(t *testing.T) { encryptionService: ossencryption.ProvideService(), log: log.New("test logger"), } - _, err := cfgProvider.readConfig(incorrectSettings) + _, err := cfgProvider.readConfig(context.Background(), incorrectSettings) require.NotNil(t, err) require.Equal(t, err.Error(), "alert validation error: token must be specified when using the Slack chat API") }) @@ -362,7 +363,7 @@ func TestNotificationAsConfig(t *testing.T) { func setupBusHandlers(sqlStore *sqlstore.SQLStore) { bus.AddHandler("getOrg", func(q *models.GetOrgByNameQuery) error { - return sqlstore.GetOrgByName(q) + return sqlstore.GetOrgByName(context.Background(), q) }) bus.AddHandler("getAlertNotifications", func(q *models.GetAlertNotificationsWithUidQuery) error { diff --git a/pkg/services/provisioning/provisioning.go b/pkg/services/provisioning/provisioning.go index 843701f3b5f..d744d9d3b0c 100644 --- a/pkg/services/provisioning/provisioning.go +++ b/pkg/services/provisioning/provisioning.go @@ -39,7 +39,7 @@ type ProvisioningService interface { RunInitProvisioners(ctx context.Context) error ProvisionDatasources(ctx context.Context) error ProvisionPlugins() error - ProvisionNotifications() error + ProvisionNotifications(ctx context.Context) error ProvisionDashboards(ctx context.Context) error GetDashboardProvisionerResolvedPath(name string) string GetAllowUIUpdatesFromConfig(name string) bool @@ -59,7 +59,7 @@ func NewProvisioningServiceImpl() *ProvisioningServiceImpl { // Used for testing purposes func newProvisioningServiceImpl( newDashboardProvisioner dashboards.DashboardProvisionerFactory, - provisionNotifiers func(string, encryption.Service) error, + provisionNotifiers func(context.Context, string, encryption.Service) error, provisionDatasources func(context.Context, string) error, provisionPlugins func(string, plugifaces.Store) error, ) *ProvisioningServiceImpl { @@ -81,7 +81,7 @@ type ProvisioningServiceImpl struct { pollingCtxCancel context.CancelFunc newDashboardProvisioner dashboards.DashboardProvisionerFactory dashboardProvisioner dashboards.DashboardProvisioner - provisionNotifiers func(string, encryption.Service) error + provisionNotifiers func(context.Context, string, encryption.Service) error provisionDatasources func(context.Context, string) error provisionPlugins func(string, plugifaces.Store) error mutex sync.Mutex @@ -98,7 +98,7 @@ func (ps *ProvisioningServiceImpl) RunInitProvisioners(ctx context.Context) erro return err } - err = ps.ProvisionNotifications() + err = ps.ProvisionNotifications(ctx) if err != nil { return err } @@ -147,15 +147,15 @@ func (ps *ProvisioningServiceImpl) ProvisionPlugins() error { return errutil.Wrap("app provisioning error", err) } -func (ps *ProvisioningServiceImpl) ProvisionNotifications() error { +func (ps *ProvisioningServiceImpl) ProvisionNotifications(ctx context.Context) error { alertNotificationsPath := filepath.Join(ps.Cfg.ProvisioningPath, "notifiers") - err := ps.provisionNotifiers(alertNotificationsPath, ps.EncryptionService) + err := ps.provisionNotifiers(ctx, alertNotificationsPath, ps.EncryptionService) return errutil.Wrap("Alert notification provisioning error", err) } func (ps *ProvisioningServiceImpl) ProvisionDashboards(ctx context.Context) error { dashboardPath := filepath.Join(ps.Cfg.ProvisioningPath, "dashboards") - dashProvisioner, err := ps.newDashboardProvisioner(dashboardPath, ps.SQLStore) + dashProvisioner, err := ps.newDashboardProvisioner(ctx, dashboardPath, ps.SQLStore) if err != nil { return errutil.Wrap("Failed to create provisioner", err) } diff --git a/pkg/services/provisioning/provisioning_mock.go b/pkg/services/provisioning/provisioning_mock.go index 8f590bfa034..8a947a26cd9 100644 --- a/pkg/services/provisioning/provisioning_mock.go +++ b/pkg/services/provisioning/provisioning_mock.go @@ -25,7 +25,7 @@ type ProvisioningServiceMock struct { RunFunc func(ctx context.Context) error } -func NewProvisioningServiceMock() *ProvisioningServiceMock { +func NewProvisioningServiceMock(ctx context.Context) *ProvisioningServiceMock { return &ProvisioningServiceMock{ Calls: &Calls{}, } @@ -55,7 +55,7 @@ func (mock *ProvisioningServiceMock) ProvisionPlugins() error { return nil } -func (mock *ProvisioningServiceMock) ProvisionNotifications() error { +func (mock *ProvisioningServiceMock) ProvisionNotifications(ctx context.Context) error { mock.Calls.ProvisionNotifications = append(mock.Calls.ProvisionNotifications, nil) if mock.ProvisionNotificationsFunc != nil { return mock.ProvisionNotificationsFunc() diff --git a/pkg/services/provisioning/provisioning_test.go b/pkg/services/provisioning/provisioning_test.go index b5bb601f1f4..731b3c0a3ce 100644 --- a/pkg/services/provisioning/provisioning_test.go +++ b/pkg/services/provisioning/provisioning_test.go @@ -92,7 +92,7 @@ func setup() *serviceTestStruct { } serviceTest.service = newProvisioningServiceImpl( - func(string, dboards.Store) (dashboards.DashboardProvisioner, error) { + func(context.Context, string, dboards.Store) (dashboards.DashboardProvisioner, error) { return serviceTest.mock, nil }, nil, diff --git a/pkg/services/provisioning/utils/utils.go b/pkg/services/provisioning/utils/utils.go index 99f1c7a3c79..1ade4da8b18 100644 --- a/pkg/services/provisioning/utils/utils.go +++ b/pkg/services/provisioning/utils/utils.go @@ -1,6 +1,7 @@ package utils import ( + "context" "errors" "fmt" @@ -8,9 +9,9 @@ import ( "github.com/grafana/grafana/pkg/models" ) -func CheckOrgExists(orgID int64) error { +func CheckOrgExists(ctx context.Context, orgID int64) error { query := models.GetOrgByIdQuery{Id: orgID} - if err := bus.Dispatch(&query); err != nil { + if err := bus.DispatchCtx(ctx, &query); err != nil { if errors.Is(err, models.ErrOrgNotFound) { return err } diff --git a/pkg/services/provisioning/utils/utils_test.go b/pkg/services/provisioning/utils/utils_test.go index 0e78e0cfcfd..88019f932b7 100644 --- a/pkg/services/provisioning/utils/utils_test.go +++ b/pkg/services/provisioning/utils/utils_test.go @@ -1,6 +1,7 @@ package utils import ( + "context" "testing" "github.com/grafana/grafana/pkg/models" @@ -14,16 +15,16 @@ func TestCheckOrgExists(t *testing.T) { sqlstore.InitTestDB(t) defaultOrg := models.CreateOrgCommand{Name: "Main Org."} - err := sqlstore.CreateOrg(&defaultOrg) + err := sqlstore.CreateOrg(context.Background(), &defaultOrg) require.NoError(t, err) t.Run("default org exists", func(t *testing.T) { - err := CheckOrgExists(defaultOrg.Result.Id) + err := CheckOrgExists(context.Background(), defaultOrg.Result.Id) require.NoError(t, err) }) t.Run("other org doesn't exist", func(t *testing.T) { - err := CheckOrgExists(defaultOrg.Result.Id + 1) + err := CheckOrgExists(context.Background(), defaultOrg.Result.Id+1) require.Equal(t, err, models.ErrOrgNotFound) }) }) diff --git a/pkg/services/sqlstore/org.go b/pkg/services/sqlstore/org.go index e16a369b02d..01464b21c42 100644 --- a/pkg/services/sqlstore/org.go +++ b/pkg/services/sqlstore/org.go @@ -16,16 +16,16 @@ import ( const MainOrgName = "Main Org." func init() { - bus.AddHandler("sql", GetOrgById) - bus.AddHandler("sql", CreateOrg) - bus.AddHandler("sql", UpdateOrg) - bus.AddHandler("sql", UpdateOrgAddress) - bus.AddHandler("sql", GetOrgByName) - bus.AddHandler("sql", SearchOrgs) - bus.AddHandler("sql", DeleteOrg) + bus.AddHandlerCtx("sql", GetOrgById) + bus.AddHandlerCtx("sql", CreateOrg) + bus.AddHandlerCtx("sql", UpdateOrg) + bus.AddHandlerCtx("sql", UpdateOrgAddress) + bus.AddHandlerCtx("sql", GetOrgByName) + bus.AddHandlerCtx("sql", SearchOrgs) + bus.AddHandlerCtx("sql", DeleteOrg) } -func SearchOrgs(query *models.SearchOrgsQuery) error { +func SearchOrgs(ctx context.Context, query *models.SearchOrgsQuery) error { query.Result = make([]*models.OrgDTO, 0) sess := x.Table("org") if query.Query != "" { @@ -48,7 +48,7 @@ func SearchOrgs(query *models.SearchOrgsQuery) error { return err } -func GetOrgById(query *models.GetOrgByIdQuery) error { +func GetOrgById(ctx context.Context, query *models.GetOrgByIdQuery) error { var org models.Org exists, err := x.Id(query.Id).Get(&org) if err != nil { @@ -63,7 +63,7 @@ func GetOrgById(query *models.GetOrgByIdQuery) error { return nil } -func GetOrgByName(query *models.GetOrgByNameQuery) error { +func GetOrgByName(ctx context.Context, query *models.GetOrgByNameQuery) error { var org models.Org exists, err := x.Where("name=?", query.Name).Get(&org) if err != nil { @@ -154,7 +154,7 @@ func (ss *SQLStore) CreateOrgWithMember(name string, userID int64) (models.Org, return createOrg(name, userID, ss.engine) } -func CreateOrg(cmd *models.CreateOrgCommand) error { +func CreateOrg(ctx context.Context, cmd *models.CreateOrgCommand) error { org, err := createOrg(cmd.Name, cmd.UserId, x) if err != nil { return err @@ -164,7 +164,7 @@ func CreateOrg(cmd *models.CreateOrgCommand) error { return nil } -func UpdateOrg(cmd *models.UpdateOrgCommand) error { +func UpdateOrg(ctx context.Context, cmd *models.UpdateOrgCommand) error { return inTransaction(func(sess *DBSession) error { if isNameTaken, err := isOrgNameTaken(cmd.Name, cmd.OrgId, sess); err != nil { return err @@ -197,7 +197,7 @@ func UpdateOrg(cmd *models.UpdateOrgCommand) error { }) } -func UpdateOrgAddress(cmd *models.UpdateOrgAddressCommand) error { +func UpdateOrgAddress(ctx context.Context, cmd *models.UpdateOrgAddressCommand) error { return inTransaction(func(sess *DBSession) error { org := models.Org{ Address1: cmd.Address1, @@ -224,7 +224,7 @@ func UpdateOrgAddress(cmd *models.UpdateOrgAddressCommand) error { }) } -func DeleteOrg(cmd *models.DeleteOrgCommand) error { +func DeleteOrg(ctx context.Context, cmd *models.DeleteOrgCommand) error { return inTransaction(func(sess *DBSession) error { if res, err := sess.Query("SELECT 1 from org WHERE id=?", cmd.Id); err != nil { return err diff --git a/pkg/services/sqlstore/org_test.go b/pkg/services/sqlstore/org_test.go index 83b7d1545ce..376fad7be68 100644 --- a/pkg/services/sqlstore/org_test.go +++ b/pkg/services/sqlstore/org_test.go @@ -25,14 +25,14 @@ func TestAccountDataAccess(t *testing.T) { for i := 1; i < 4; i++ { cmd = &models.CreateOrgCommand{Name: fmt.Sprint("Org #", i)} - err = CreateOrg(cmd) + err = CreateOrg(context.Background(), cmd) require.NoError(t, err) ids = append(ids, cmd.Result.Id) } query := &models.SearchOrgsQuery{Ids: ids} - err = SearchOrgs(query) + err = SearchOrgs(context.Background(), query) require.NoError(t, err) require.Equal(t, len(query.Result), 3) @@ -42,13 +42,13 @@ func TestAccountDataAccess(t *testing.T) { sqlStore = InitTestDB(t) for i := 1; i < 4; i++ { cmd := &models.CreateOrgCommand{Name: fmt.Sprint("Org #", i)} - err := CreateOrg(cmd) + err := CreateOrg(context.Background(), cmd) require.NoError(t, err) } t.Run("Should be able to search with defaults", func(t *testing.T) { query := &models.SearchOrgsQuery{} - err := SearchOrgs(query) + err := SearchOrgs(context.Background(), query) require.NoError(t, err) require.Equal(t, len(query.Result), 3) @@ -56,7 +56,7 @@ func TestAccountDataAccess(t *testing.T) { t.Run("Should be able to limit search", func(t *testing.T) { query := &models.SearchOrgsQuery{Limit: 1} - err := SearchOrgs(query) + err := SearchOrgs(context.Background(), query) require.NoError(t, err) require.Equal(t, len(query.Result), 1) @@ -64,7 +64,7 @@ func TestAccountDataAccess(t *testing.T) { t.Run("Should be able to limit and paginate search", func(t *testing.T) { query := &models.SearchOrgsQuery{Limit: 2, Page: 1} - err := SearchOrgs(query) + err := SearchOrgs(context.Background(), query) require.NoError(t, err) require.Equal(t, len(query.Result), 1) @@ -278,7 +278,7 @@ func TestAccountDataAccess(t *testing.T) { t.Run("Removing user from org should delete user completely if in no other org", func(t *testing.T) { // make sure ac2 has no org - err := DeleteOrg(&models.DeleteOrgCommand{Id: ac2.OrgId}) + err := DeleteOrg(context.Background(), &models.DeleteOrgCommand{Id: ac2.OrgId}) require.NoError(t, err) // remove ac2 user from ac1 org diff --git a/pkg/services/sqlstore/quota_test.go b/pkg/services/sqlstore/quota_test.go index 81a24316b94..8358ce2baa2 100644 --- a/pkg/services/sqlstore/quota_test.go +++ b/pkg/services/sqlstore/quota_test.go @@ -49,7 +49,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { UserId: 1, } - err := CreateOrg(&userCmd) + err := CreateOrg(context.Background(), &userCmd) require.NoError(t, err) orgId = userCmd.Result.Id diff --git a/pkg/services/sqlstore/stats_test.go b/pkg/services/sqlstore/stats_test.go index 7e9b126e3cb..5e44dba06e1 100644 --- a/pkg/services/sqlstore/stats_test.go +++ b/pkg/services/sqlstore/stats_test.go @@ -78,7 +78,7 @@ func populateDB(t *testing.T, sqlStore *SQLStore) { // get 1st user's organisation getOrgByIdQuery := &models.GetOrgByIdQuery{Id: users[0].OrgId} - err := GetOrgById(getOrgByIdQuery) + err := GetOrgById(context.Background(), getOrgByIdQuery) require.NoError(t, err) org := getOrgByIdQuery.Result @@ -102,7 +102,7 @@ func populateDB(t *testing.T, sqlStore *SQLStore) { // get 2nd user's organisation getOrgByIdQuery = &models.GetOrgByIdQuery{Id: users[1].OrgId} - err = GetOrgById(getOrgByIdQuery) + err = GetOrgById(context.Background(), getOrgByIdQuery) require.NoError(t, err) org = getOrgByIdQuery.Result diff --git a/pkg/services/sqlstore/user_test.go b/pkg/services/sqlstore/user_test.go index 888b659208d..6166cff45e4 100644 --- a/pkg/services/sqlstore/user_test.go +++ b/pkg/services/sqlstore/user_test.go @@ -80,7 +80,7 @@ func TestUserDataAccess(t *testing.T) { }() orgCmd := &models.CreateOrgCommand{Name: "Some Test Org"} - err := CreateOrg(orgCmd) + err := CreateOrg(context.Background(), orgCmd) require.Nil(t, err) cmd := models.CreateUserCommand{