diff --git a/pkg/api/admin_encryption.go b/pkg/api/admin_encryption.go index 579fa1b3dd4..9f00aa2efd5 100644 --- a/pkg/api/admin_encryption.go +++ b/pkg/api/admin_encryption.go @@ -54,7 +54,7 @@ func (hs *HTTPServer) AdminRollbackSecrets(c *models.ReqContext) response.Respon // To migrate to the plugin, it must be installed and configured // so as not to lose access to migrated secrets func (hs *HTTPServer) AdminMigrateSecretsToPlugin(c *models.ReqContext) response.Response { - if skv.EvaluateRemoteSecretsPlugin(hs.secretsPluginManager, hs.Cfg) != nil { + if skv.EvaluateRemoteSecretsPlugin(c.Req.Context(), hs.secretsPluginManager, hs.Cfg) != nil { hs.log.Warn("Received secrets plugin migration request while plugin is not available") return response.Respond(http.StatusBadRequest, "Secrets plugin is not available") } @@ -69,7 +69,7 @@ func (hs *HTTPServer) AdminMigrateSecretsToPlugin(c *models.ReqContext) response // To migrate from the plugin, it must be installed only // as it is possible the user disabled it and then wants to migrate func (hs *HTTPServer) AdminMigrateSecretsFromPlugin(c *models.ReqContext) response.Response { - if hs.secretsPluginManager.SecretsManager() == nil { + if hs.secretsPluginManager.SecretsManager(c.Req.Context()) == nil { hs.log.Warn("Received secrets plugin migration request while plugin is not installed") return response.Respond(http.StatusBadRequest, "Secrets plugin is not installed") } @@ -82,7 +82,7 @@ func (hs *HTTPServer) AdminMigrateSecretsFromPlugin(c *models.ReqContext) respon } func (hs *HTTPServer) AdminDeleteAllSecretsManagerPluginSecrets(c *models.ReqContext) response.Response { - if hs.secretsPluginManager.SecretsManager() == nil { + if hs.secretsPluginManager.SecretsManager(c.Req.Context()) == nil { hs.log.Warn("Received secrets plugin deletion request while plugin is not installed") return response.Respond(http.StatusBadRequest, "Secrets plugin is not installed") } diff --git a/pkg/api/fakes.go b/pkg/api/fakes.go index 6a424d90925..3eba2475d59 100644 --- a/pkg/api/fakes.go +++ b/pkg/api/fakes.go @@ -59,7 +59,7 @@ type fakeRendererManager struct { plugins.RendererManager } -func (ps *fakeRendererManager) Renderer() *plugins.Plugin { +func (ps *fakeRendererManager) Renderer(_ context.Context) *plugins.Plugin { return nil } diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index e9d8e6c712f..2b73df3b5f3 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -88,7 +88,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i } hasAccess := accesscontrol.HasAccess(hs.AccessControl, c) - secretsManagerPluginEnabled := kvstore.EvaluateRemoteSecretsPlugin(hs.secretsPluginManager, hs.Cfg) == nil + secretsManagerPluginEnabled := kvstore.EvaluateRemoteSecretsPlugin(c.Req.Context(), hs.secretsPluginManager, hs.Cfg) == nil jsonObj := map[string]interface{}{ "defaultDatasource": defaultDS, @@ -154,7 +154,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i "enabledFeatures": hs.License.EnabledFeatures(), }, "featureToggles": hs.Features.GetEnabled(c.Req.Context()), - "rendererAvailable": hs.RenderService.IsAvailable(), + "rendererAvailable": hs.RenderService.IsAvailable(c.Req.Context()), "rendererVersion": hs.RenderService.Version(), "secretsManagerPluginEnabled": secretsManagerPluginEnabled, "http2Enabled": hs.Cfg.Protocol == setting.HTTP2Scheme, diff --git a/pkg/cmd/grafana-cli/runner/wire.go b/pkg/cmd/grafana-cli/runner/wire.go index cafadbf0c5c..4014abdee55 100644 --- a/pkg/cmd/grafana-cli/runner/wire.go +++ b/pkg/cmd/grafana-cli/runner/wire.go @@ -181,12 +181,12 @@ var wireSet = wire.NewSet( wire.Bind(new(repo.Service), new(*repo.Manager)), manager.ProvideService, wire.Bind(new(plugins.Manager), new(*manager.PluginManager)), + wire.Bind(new(plugins.RendererManager), new(*manager.PluginManager)), + wire.Bind(new(plugins.SecretsPluginManager), new(*manager.PluginManager)), client.ProvideService, wire.Bind(new(plugins.Client), new(*client.Service)), managerStore.ProvideService, wire.Bind(new(plugins.Store), new(*managerStore.Service)), - wire.Bind(new(plugins.RendererManager), new(*managerStore.Service)), - wire.Bind(new(plugins.SecretsPluginManager), new(*managerStore.Service)), wire.Bind(new(plugins.StaticRouteResolver), new(*managerStore.Service)), pluginDashboards.ProvideFileStoreManager, wire.Bind(new(pluginDashboards.FileStore), new(*pluginDashboards.FileStoreManager)), diff --git a/pkg/plugins/ifaces.go b/pkg/plugins/ifaces.go index c26c4419a3e..4ce31f17c18 100644 --- a/pkg/plugins/ifaces.go +++ b/pkg/plugins/ifaces.go @@ -54,12 +54,12 @@ type BackendFactoryProvider interface { type RendererManager interface { // Renderer returns a renderer plugin. - Renderer() *Plugin + Renderer(ctx context.Context) *Plugin } type SecretsPluginManager interface { // SecretsManager returns a secretsmanager plugin - SecretsManager() *Plugin + SecretsManager(ctx context.Context) *Plugin } type StaticRouteResolver interface { diff --git a/pkg/plugins/manager/manager.go b/pkg/plugins/manager/manager.go index a51cc92860b..326b735e88a 100644 --- a/pkg/plugins/manager/manager.go +++ b/pkg/plugins/manager/manager.go @@ -17,6 +17,8 @@ import ( ) var _ plugins.Manager = (*PluginManager)(nil) +var _ plugins.RendererManager = (*PluginManager)(nil) +var _ plugins.SecretsPluginManager = (*PluginManager)(nil) type PluginManager struct { cfg *plugins.Cfg @@ -172,6 +174,24 @@ func (m *PluginManager) Remove(ctx context.Context, pluginID string) error { return m.pluginStorage.Remove(ctx, plugin.ID) } +func (m *PluginManager) Renderer(ctx context.Context) *plugins.Plugin { + for _, p := range m.pluginRegistry.Plugins(ctx) { + if p.IsRenderer() && !p.IsDecommissioned() { + return p + } + } + return nil +} + +func (m *PluginManager) SecretsManager(ctx context.Context) *plugins.Plugin { + for _, p := range m.pluginRegistry.Plugins(ctx) { + if p.IsSecretsManager() && !p.IsDecommissioned() { + return p + } + } + return nil +} + // plugin finds a plugin with `pluginID` from the registry that is not decommissioned func (m *PluginManager) plugin(ctx context.Context, pluginID string) (*plugins.Plugin, bool) { p, exists := m.pluginRegistry.Plugin(ctx, pluginID) diff --git a/pkg/plugins/manager/manager_test.go b/pkg/plugins/manager/manager_test.go index ca1fb548810..41d18e791af 100644 --- a/pkg/plugins/manager/manager_test.go +++ b/pkg/plugins/manager/manager_test.go @@ -213,6 +213,52 @@ func TestPluginManager_Run(t *testing.T) { }) } +func TestManager_Renderer(t *testing.T) { + t.Run("Renderer returns a single (non-decommissioned) renderer plugin", func(t *testing.T) { + p1 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-renderer", Type: plugins.Renderer}} + p2 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-panel", Type: plugins.Panel}} + p3 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-app", Type: plugins.App}} + + reg := &fakes.FakePluginRegistry{ + Store: map[string]*plugins.Plugin{ + p1.ID: p1, + p2.ID: p2, + p3.ID: p3, + }, + } + + pm := New(&plugins.Cfg{}, reg, []plugins.PluginSource{}, &fakes.FakeLoader{}, &fakes.FakePluginRepo{}, + &fakes.FakePluginStorage{}, &fakes.FakeProcessManager{}) + + r := pm.Renderer(context.Background()) + require.Equal(t, p1, r) + }) +} + +func TestManager_SecretsManager(t *testing.T) { + t.Run("Renderer returns a single (non-decommissioned) secrets manager plugin", func(t *testing.T) { + p1 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-renderer", Type: plugins.Renderer}} + p2 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-panel", Type: plugins.Panel}} + p3 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-secrets", Type: plugins.SecretsManager}} + p4 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-datasource", Type: plugins.DataSource}} + + reg := &fakes.FakePluginRegistry{ + Store: map[string]*plugins.Plugin{ + p1.ID: p1, + p2.ID: p2, + p3.ID: p3, + p4.ID: p4, + }, + } + + pm := New(&plugins.Cfg{}, reg, []plugins.PluginSource{}, &fakes.FakeLoader{}, &fakes.FakePluginRepo{}, + &fakes.FakePluginStorage{}, &fakes.FakeProcessManager{}) + + r := pm.SecretsManager(context.Background()) + require.Equal(t, p3, r) + }) +} + func createPlugin(t *testing.T, pluginID string, class plugins.Class, managed, backend bool, cbs ...func(*plugins.Plugin)) *plugins.Plugin { t.Helper() diff --git a/pkg/plugins/manager/store/store.go b/pkg/plugins/manager/store/store.go index c80696bea7d..4fa6a3d927b 100644 --- a/pkg/plugins/manager/store/store.go +++ b/pkg/plugins/manager/store/store.go @@ -9,8 +9,6 @@ import ( ) var _ plugins.Store = (*Service)(nil) -var _ plugins.RendererManager = (*Service)(nil) -var _ plugins.SecretsPluginManager = (*Service)(nil) type Service struct { pluginRegistry registry.Service @@ -51,26 +49,6 @@ func (s *Service) Plugins(ctx context.Context, pluginTypes ...plugins.Type) []pl return pluginsList } -func (s *Service) Renderer() *plugins.Plugin { - for _, p := range s.availablePlugins(context.TODO()) { - if p.IsRenderer() { - return p - } - } - - return nil -} - -func (s *Service) SecretsManager() *plugins.Plugin { - for _, p := range s.availablePlugins(context.TODO()) { - if p.IsSecretsManager() { - return p - } - } - - return nil -} - // plugin finds a plugin with `pluginID` from the registry that is not decommissioned func (s *Service) plugin(ctx context.Context, pluginID string) (*plugins.Plugin, bool) { p, exists := s.pluginRegistry.Plugin(ctx, pluginID) diff --git a/pkg/plugins/manager/store/store_test.go b/pkg/plugins/manager/store/store_test.go index f11f102128e..da88974d607 100644 --- a/pkg/plugins/manager/store/store_test.go +++ b/pkg/plugins/manager/store/store_test.go @@ -69,49 +69,6 @@ func TestStore_Plugins(t *testing.T) { }) } -func TestStore_Renderer(t *testing.T) { - t.Run("Renderer returns a single (non-decommissioned) renderer plugin", func(t *testing.T) { - p1 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-renderer", Type: plugins.Renderer}} - p2 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-panel", Type: plugins.Panel}} - p3 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-app", Type: plugins.App}} - p4 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-datasource", Type: plugins.DataSource}} - p4.RegisterClient(&DecommissionedPlugin{}) - - ps := ProvideService( - newFakePluginRegistry(map[string]*plugins.Plugin{ - p1.ID: p1, - p2.ID: p2, - p3.ID: p3, - p4.ID: p4, - }), - ) - - r := ps.Renderer() - require.Equal(t, p1, r) - }) -} - -func TestStore_SecretsManager(t *testing.T) { - t.Run("Renderer returns a single (non-decommissioned) secrets manager plugin", func(t *testing.T) { - p1 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-renderer", Type: plugins.Renderer}} - p2 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-panel", Type: plugins.Panel}} - p3 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-secrets", Type: plugins.SecretsManager}} - p4 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-datasource", Type: plugins.DataSource}} - - ps := ProvideService( - newFakePluginRegistry(map[string]*plugins.Plugin{ - p1.ID: p1, - p2.ID: p2, - p3.ID: p3, - p4.ID: p4, - }), - ) - - r := ps.SecretsManager() - require.Equal(t, p3, r) - }) -} - func TestStore_Routes(t *testing.T) { t.Run("Routes returns all static routes for non-decommissioned plugins", func(t *testing.T) { p1 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "a-test-renderer", Type: plugins.Renderer}, PluginDir: "/some/dir"} diff --git a/pkg/server/wire.go b/pkg/server/wire.go index 3f06be866a2..a3457e964c4 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -176,12 +176,12 @@ var wireBasicSet = wire.NewSet( wire.Bind(new(repo.Service), new(*repo.Manager)), manager.ProvideService, wire.Bind(new(plugins.Manager), new(*manager.PluginManager)), + wire.Bind(new(plugins.RendererManager), new(*manager.PluginManager)), + wire.Bind(new(plugins.SecretsPluginManager), new(*manager.PluginManager)), client.ProvideService, wire.Bind(new(plugins.Client), new(*client.Service)), managerStore.ProvideService, wire.Bind(new(plugins.Store), new(*managerStore.Service)), - wire.Bind(new(plugins.RendererManager), new(*managerStore.Service)), - wire.Bind(new(plugins.SecretsPluginManager), new(*managerStore.Service)), wire.Bind(new(plugins.StaticRouteResolver), new(*managerStore.Service)), pluginDashboards.ProvideFileStoreManager, wire.Bind(new(pluginDashboards.FileStore), new(*pluginDashboards.FileStoreManager)), diff --git a/pkg/services/alerting/notifier_test.go b/pkg/services/alerting/notifier_test.go index d53413c9822..92d18d32842 100644 --- a/pkg/services/alerting/notifier_test.go +++ b/pkg/services/alerting/notifier_test.go @@ -243,7 +243,7 @@ func notificationServiceScenario(t *testing.T, name string, evalCtx *EvalContext scenarioCtx.rendererAvailable = true renderService := &testRenderService{ - isAvailableProvider: func() bool { + isAvailableProvider: func(ctx context.Context) bool { return scenarioCtx.rendererAvailable }, renderProvider: func(ctx context.Context, opts rendering.Opts) (*rendering.RenderResult, error) { @@ -334,7 +334,7 @@ func (n *testNotifier) GetFrequency() time.Duration { var _ Notifier = &testNotifier{} type testRenderService struct { - isAvailableProvider func() bool + isAvailableProvider func(ctx context.Context) bool renderProvider func(ctx context.Context, opts rendering.Opts) (*rendering.RenderResult, error) renderErrorImageProvider func(error error) (*rendering.RenderResult, error) } @@ -343,13 +343,13 @@ func (s *testRenderService) SanitizeSVG(ctx context.Context, req *rendering.Sani return &rendering.SanitizeSVGResponse{Sanitized: req.Content}, nil } -func (s *testRenderService) HasCapability(feature rendering.CapabilityName) (rendering.CapabilitySupportRequestResult, error) { +func (s *testRenderService) HasCapability(_ context.Context, feature rendering.CapabilityName) (rendering.CapabilitySupportRequestResult, error) { return rendering.CapabilitySupportRequestResult{}, nil } -func (s *testRenderService) IsAvailable() bool { +func (s *testRenderService) IsAvailable(ctx context.Context) bool { if s.isAvailableProvider != nil { - return s.isAvailableProvider() + return s.isAvailableProvider(ctx) } return true diff --git a/pkg/services/rendering/capabilities.go b/pkg/services/rendering/capabilities.go index 2087577ed04..f4eaa4eddcd 100644 --- a/pkg/services/rendering/capabilities.go +++ b/pkg/services/rendering/capabilities.go @@ -1,6 +1,7 @@ package rendering import ( + "context" "errors" "github.com/Masterminds/semver" @@ -22,8 +23,8 @@ const ( var ErrUnknownCapability = errors.New("unknown capability") var ErrInvalidPluginVersion = errors.New("invalid plugin version") -func (rs *RenderingService) HasCapability(capability CapabilityName) (CapabilitySupportRequestResult, error) { - if !rs.IsAvailable() { +func (rs *RenderingService) HasCapability(ctx context.Context, capability CapabilityName) (CapabilitySupportRequestResult, error) { + if !rs.IsAvailable(ctx) { return CapabilitySupportRequestResult{IsSupported: false, SemverConstraint: ""}, ErrRenderUnavailable } diff --git a/pkg/services/rendering/capabilities_test.go b/pkg/services/rendering/capabilities_test.go index eec3382c96f..f0faab7c6a5 100644 --- a/pkg/services/rendering/capabilities_test.go +++ b/pkg/services/rendering/capabilities_test.go @@ -1,6 +1,7 @@ package rendering import ( + "context" "testing" "github.com/stretchr/testify/require" @@ -12,7 +13,7 @@ import ( type dummyPluginManager struct{} -func (d *dummyPluginManager) Renderer() *plugins.Plugin { +func (d *dummyPluginManager) Renderer(_ context.Context) *plugins.Plugin { return nil } @@ -123,7 +124,7 @@ func TestCapabilities(t *testing.T) { t.Run(tt.name, func(t *testing.T) { rs.Cfg.RendererUrl = tt.rendererUrl rs.version = tt.rendererVersion - res, err := rs.HasCapability(tt.capabilityName) + res, err := rs.HasCapability(context.Background(), tt.capabilityName) if tt.expectedError == nil { require.NoError(t, err) diff --git a/pkg/services/rendering/interface.go b/pkg/services/rendering/interface.go index a7accdffec4..859ebf112f7 100644 --- a/pkg/services/rendering/interface.go +++ b/pkg/services/rendering/interface.go @@ -117,13 +117,13 @@ type CapabilitySupportRequestResult struct { //go:generate mockgen -destination=mock.go -package=rendering github.com/grafana/grafana/pkg/services/rendering Service type Service interface { - IsAvailable() bool + IsAvailable(ctx context.Context) bool Version() string Render(ctx context.Context, opts Opts, session Session) (*RenderResult, error) RenderCSV(ctx context.Context, opts CSVOpts, session Session) (*RenderCSVResult, error) RenderErrorImage(theme models.Theme, error error) (*RenderResult, error) GetRenderUser(ctx context.Context, key string) (*RenderUser, bool) - HasCapability(capability CapabilityName) (CapabilitySupportRequestResult, error) + HasCapability(ctx context.Context, capability CapabilityName) (CapabilitySupportRequestResult, error) CreateRenderingSession(ctx context.Context, authOpts AuthOpts, sessionOpts SessionOpts) (Session, error) SanitizeSVG(ctx context.Context, req *SanitizeSVGRequest) (*SanitizeSVGResponse, error) } diff --git a/pkg/services/rendering/mock.go b/pkg/services/rendering/mock.go index 705a05a1f9f..6d5d0f33f92 100644 --- a/pkg/services/rendering/mock.go +++ b/pkg/services/rendering/mock.go @@ -66,32 +66,32 @@ func (mr *MockServiceMockRecorder) GetRenderUser(arg0, arg1 interface{}) *gomock } // HasCapability mocks base method. -func (m *MockService) HasCapability(arg0 CapabilityName) (CapabilitySupportRequestResult, error) { +func (m *MockService) HasCapability(arg0 context.Context, arg1 CapabilityName) (CapabilitySupportRequestResult, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HasCapability", arg0) + ret := m.ctrl.Call(m, "HasCapability", arg0, arg1) ret0, _ := ret[0].(CapabilitySupportRequestResult) ret1, _ := ret[1].(error) return ret0, ret1 } // HasCapability indicates an expected call of HasCapability. -func (mr *MockServiceMockRecorder) HasCapability(arg0 interface{}) *gomock.Call { +func (mr *MockServiceMockRecorder) HasCapability(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasCapability", reflect.TypeOf((*MockService)(nil).HasCapability), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasCapability", reflect.TypeOf((*MockService)(nil).HasCapability), arg0, arg1) } // IsAvailable mocks base method. -func (m *MockService) IsAvailable() bool { +func (m *MockService) IsAvailable(arg0 context.Context) bool { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsAvailable") + ret := m.ctrl.Call(m, "IsAvailable", arg0) ret0, _ := ret[0].(bool) return ret0 } // IsAvailable indicates an expected call of IsAvailable. -func (mr *MockServiceMockRecorder) IsAvailable() *gomock.Call { +func (mr *MockServiceMockRecorder) IsAvailable(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsAvailable", reflect.TypeOf((*MockService)(nil).IsAvailable)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsAvailable", reflect.TypeOf((*MockService)(nil).IsAvailable), arg0) } // Render mocks base method. diff --git a/pkg/services/rendering/rendering.go b/pkg/services/rendering/rendering.go index 75f33a84e85..1ea316187d2 100644 --- a/pkg/services/rendering/rendering.go +++ b/pkg/services/rendering/rendering.go @@ -156,9 +156,9 @@ func (rs *RenderingService) Run(ctx context.Context) error { } } - if rs.pluginAvailable() { + if rs.pluginAvailable(ctx) { rs.log = rs.log.New("renderer", "plugin") - rs.pluginInfo = rs.RendererPluginManager.Renderer() + rs.pluginInfo = rs.RendererPluginManager.Renderer(ctx) if err := rs.startPlugin(ctx); err != nil { return err @@ -191,16 +191,16 @@ func (rs *RenderingService) Run(ctx context.Context) error { return nil } -func (rs *RenderingService) pluginAvailable() bool { - return rs.RendererPluginManager.Renderer() != nil +func (rs *RenderingService) pluginAvailable(ctx context.Context) bool { + return rs.RendererPluginManager.Renderer(ctx) != nil } func (rs *RenderingService) remoteAvailable() bool { return rs.Cfg.RendererUrl != "" } -func (rs *RenderingService) IsAvailable() bool { - return rs.remoteAvailable() || rs.pluginAvailable() +func (rs *RenderingService) IsAvailable(ctx context.Context) bool { + return rs.remoteAvailable() || rs.pluginAvailable(ctx) } func (rs *RenderingService) Version() string { @@ -271,7 +271,7 @@ func (rs *RenderingService) render(ctx context.Context, opts Opts, renderKeyProv }, nil } - if !rs.IsAvailable() { + if !rs.IsAvailable(ctx) { rs.log.Warn("Could not render image, no image renderer found/installed. " + "For image rendering support please install the grafana-image-renderer plugin. " + "Read more at https://grafana.com/docs/grafana/latest/administration/image_rendering/") @@ -316,7 +316,7 @@ func (rs *RenderingService) RenderCSV(ctx context.Context, opts CSVOpts, session } func (rs *RenderingService) SanitizeSVG(ctx context.Context, req *SanitizeSVGRequest) (*SanitizeSVGResponse, error) { - capability, err := rs.HasCapability(SvgSanitization) + capability, err := rs.HasCapability(ctx, SvgSanitization) if err != nil { return nil, err } @@ -338,7 +338,7 @@ func (rs *RenderingService) renderCSV(ctx context.Context, opts CSVOpts, renderK return nil, ErrConcurrentLimitReached } - if !rs.IsAvailable() { + if !rs.IsAvailable(ctx) { return nil, ErrRenderUnavailable } diff --git a/pkg/services/rendering/rendering_test.go b/pkg/services/rendering/rendering_test.go index 5f31a016d3e..6bb798638f1 100644 --- a/pkg/services/rendering/rendering_test.go +++ b/pkg/services/rendering/rendering_test.go @@ -105,7 +105,7 @@ func TestRenderErrorImage(t *testing.T) { type unavailableRendererManager struct{} -func (m unavailableRendererManager) Renderer() *plugins.Plugin { return nil } +func (m unavailableRendererManager) Renderer(_ context.Context) *plugins.Plugin { return nil } func TestRenderUnavailableError(t *testing.T) { rs := RenderingService{ diff --git a/pkg/services/secrets/kvstore/kvstore.go b/pkg/services/secrets/kvstore/kvstore.go index 170996a9b78..1366af31e26 100644 --- a/pkg/services/secrets/kvstore/kvstore.go +++ b/pkg/services/secrets/kvstore/kvstore.go @@ -29,18 +29,19 @@ func ProvideService( ) (SecretsKVStore, error) { var logger = log.New("secrets.kvstore") var store SecretsKVStore + ctx := context.Background() store = NewSQLSecretsKVStore(sqlStore, secretsService, logger) - err := EvaluateRemoteSecretsPlugin(pluginsManager, cfg) + err := EvaluateRemoteSecretsPlugin(ctx, pluginsManager, cfg) if err != nil { logger.Debug("secrets manager evaluator returned false", "reason", err.Error()) } else { // Attempt to start the plugin var secretsPlugin secretsmanagerplugin.SecretsManagerPlugin - secretsPlugin, err = StartAndReturnPlugin(pluginsManager, context.Background()) + secretsPlugin, err = StartAndReturnPlugin(pluginsManager, ctx) namespacedKVStore := GetNamespacedKVStore(kvstore) if err != nil || secretsPlugin == nil { logger.Error("failed to start remote secrets management plugin", "msg", err.Error()) - if isFatal, readErr := IsPluginStartupErrorFatal(context.Background(), namespacedKVStore); isFatal || readErr != nil { + if isFatal, readErr := IsPluginStartupErrorFatal(ctx, namespacedKVStore); isFatal || readErr != nil { // plugin error was fatal or there was an error determining if the error was fatal logger.Error("secrets management plugin is required to start -- exiting app") if readErr != nil { diff --git a/pkg/services/secrets/kvstore/migrations/from_plugin_mig.go b/pkg/services/secrets/kvstore/migrations/from_plugin_mig.go index 160fc82b03a..53453671d8b 100644 --- a/pkg/services/secrets/kvstore/migrations/from_plugin_mig.go +++ b/pkg/services/secrets/kvstore/migrations/from_plugin_mig.go @@ -96,7 +96,7 @@ func (s *MigrateFromPluginService) Migrate(ctx context.Context) error { logger.Debug("Shutting down secrets plugin now that migration is complete") // if `use_plugin` wasn't set, stop the plugin after migration if !s.cfg.SectionWithEnvOverrides("secrets").Key("use_plugin").MustBool(false) { - err := s.manager.SecretsManager().Stop(ctx) + err := s.manager.SecretsManager(ctx).Stop(ctx) if err != nil { // Log a warning but don't throw an error logger.Error("Error stopping secrets plugin after migration", "error", err.Error()) diff --git a/pkg/services/secrets/kvstore/migrations/from_plugin_mig_test.go b/pkg/services/secrets/kvstore/migrations/from_plugin_mig_test.go index a611f086c2a..8639c4e7486 100644 --- a/pkg/services/secrets/kvstore/migrations/from_plugin_mig_test.go +++ b/pkg/services/secrets/kvstore/migrations/from_plugin_mig_test.go @@ -57,7 +57,7 @@ func setupTestMigrateFromPluginService(t *testing.T) (*MigrateFromPluginService, secretsSql := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) - return migratorService, manager.SecretsManager().SecretsManager, secretsSql + return migratorService, manager.SecretsManager(context.Background()).SecretsManager, secretsSql } func addSecretToPluginStore(t *testing.T, plugin secretsmanagerplugin.SecretsManagerPlugin, ctx context.Context, orgId int64, namespace string, typ string, value string) { diff --git a/pkg/services/secrets/kvstore/migrations/to_plugin_mig.go b/pkg/services/secrets/kvstore/migrations/to_plugin_mig.go index dfa1d36267a..6edaec466fb 100644 --- a/pkg/services/secrets/kvstore/migrations/to_plugin_mig.go +++ b/pkg/services/secrets/kvstore/migrations/to_plugin_mig.go @@ -43,7 +43,7 @@ func ProvideMigrateToPluginService( } func (s *MigrateToPluginService) Migrate(ctx context.Context) error { - if err := secretskvs.EvaluateRemoteSecretsPlugin(s.manager, s.cfg); err == nil { + if err := secretskvs.EvaluateRemoteSecretsPlugin(ctx, s.manager, s.cfg); err == nil { logger.Debug("starting migration of unified secrets to the plugin") // we need to get the fallback store since in this scenario the secrets store would be the plugin. fallbackStore := s.secretsStore.Fallback() diff --git a/pkg/services/secrets/kvstore/plugin.go b/pkg/services/secrets/kvstore/plugin.go index 35b6c954536..987b7253cac 100644 --- a/pkg/services/secrets/kvstore/plugin.go +++ b/pkg/services/secrets/kvstore/plugin.go @@ -225,12 +225,12 @@ func SetPluginStartupErrorFatal(ctx context.Context, kvstore *kvstore.Namespaced return kvstore.Set(ctx, QuitOnPluginStartupFailureKey, "true") } -func EvaluateRemoteSecretsPlugin(mg plugins.SecretsPluginManager, cfg *setting.Cfg) error { +func EvaluateRemoteSecretsPlugin(ctx context.Context, mg plugins.SecretsPluginManager, cfg *setting.Cfg) error { usePlugin := cfg.SectionWithEnvOverrides("secrets").Key("use_plugin").MustBool() if !usePlugin { return errPluginDisabledByConfig } - pluginInstalled := mg.SecretsManager() != nil + pluginInstalled := mg.SecretsManager(ctx) != nil if !pluginInstalled { return errPluginNotInstalled } @@ -240,10 +240,10 @@ func EvaluateRemoteSecretsPlugin(mg plugins.SecretsPluginManager, cfg *setting.C func StartAndReturnPlugin(mg plugins.SecretsPluginManager, ctx context.Context) (smp.SecretsManagerPlugin, error) { var err error startupOnce.Do(func() { - err = mg.SecretsManager().Start(ctx) + err = mg.SecretsManager(ctx).Start(ctx) }) if err != nil { return nil, err } - return mg.SecretsManager().SecretsManager, nil + return mg.SecretsManager(ctx).SecretsManager, nil } diff --git a/pkg/services/secrets/kvstore/plugin_test.go b/pkg/services/secrets/kvstore/plugin_test.go index 2655bf9c740..3ff32436836 100644 --- a/pkg/services/secrets/kvstore/plugin_test.go +++ b/pkg/services/secrets/kvstore/plugin_test.go @@ -52,7 +52,7 @@ func TestFatalPluginErr_FatalFlagGetsUnSetWithBackwardsCompatEnabled(t *testing. require.NotNil(t, p.SecretsKVStore) // setup - store secret and manually bypassing the remote plugin impl - _, err = p.PluginManager.SecretsManager().SecretsManager.SetSecret(context.Background(), &secretsmanagerplugin.SetSecretRequest{ + _, err = p.PluginManager.SecretsManager(context.Background()).SecretsManager.SetSecret(context.Background(), &secretsmanagerplugin.SetSecretRequest{ KeyDescriptor: &secretsmanagerplugin.Key{ OrgId: 0, Namespace: "postgres", diff --git a/pkg/services/secrets/kvstore/test_helpers.go b/pkg/services/secrets/kvstore/test_helpers.go index adf444efd85..c46cfdcdfc4 100644 --- a/pkg/services/secrets/kvstore/test_helpers.go +++ b/pkg/services/secrets/kvstore/test_helpers.go @@ -196,7 +196,7 @@ type fakePluginManager struct { plugin *plugins.Plugin } -func (mg *fakePluginManager) SecretsManager() *plugins.Plugin { +func (mg *fakePluginManager) SecretsManager(_ context.Context) *plugins.Plugin { if mg.plugin != nil { return mg.plugin } diff --git a/pkg/services/thumbs/crawler.go b/pkg/services/thumbs/crawler.go index f400d16eec9..1269d616365 100644 --- a/pkg/services/thumbs/crawler.go +++ b/pkg/services/thumbs/crawler.go @@ -123,7 +123,7 @@ func (d byOrgId) Less(i, j int) bool { return d[i].OrgId > d[j].OrgId } func (d byOrgId) Swap(i, j int) { d[i], d[j] = d[j], d[i] } func (r *simpleCrawler) Run(ctx context.Context, auth CrawlerAuth, mode CrawlerMode, theme models.Theme, thumbnailKind models.ThumbnailKind) error { - res, err := r.renderService.HasCapability(rendering.ScalingDownImages) + res, err := r.renderService.HasCapability(ctx, rendering.ScalingDownImages) if err != nil { return err } diff --git a/pkg/services/thumbs/service.go b/pkg/services/thumbs/service.go index b8e170c7dc3..4ef988b7657 100644 --- a/pkg/services/thumbs/service.go +++ b/pkg/services/thumbs/service.go @@ -317,7 +317,7 @@ func (hs *thumbService) GetDashboardPreviewsSetupSettings(c *models.ReqContext) } func (hs *thumbService) getDashboardPreviewsSetupSettings(ctx context.Context) dashboardPreviewsSetupConfig { - systemRequirements := hs.getSystemRequirements() + systemRequirements := hs.getSystemRequirements(ctx) thumbnailsExist, err := hs.thumbnailRepo.doThumbnailsExist(ctx) if err != nil { @@ -333,8 +333,8 @@ func (hs *thumbService) getDashboardPreviewsSetupSettings(ctx context.Context) d } } -func (hs *thumbService) getSystemRequirements() dashboardPreviewsSystemRequirements { - res, err := hs.renderingService.HasCapability(rendering.ScalingDownImages) +func (hs *thumbService) getSystemRequirements(ctx context.Context) dashboardPreviewsSystemRequirements { + res, err := hs.renderingService.HasCapability(ctx, rendering.ScalingDownImages) if err != nil { hs.log.Error("Error when verifying dashboard previews system requirements thumbnail", "err", err.Error()) return dashboardPreviewsSystemRequirements{