diff --git a/pkg/api/pluginproxy/ds_proxy_test.go b/pkg/api/pluginproxy/ds_proxy_test.go index 982a17092c7..61198115755 100644 --- a/pkg/api/pluginproxy/ds_proxy_test.go +++ b/pkg/api/pluginproxy/ds_proxy_test.go @@ -39,6 +39,8 @@ import ( "github.com/grafana/grafana/pkg/services/oauthtoken" "github.com/grafana/grafana/pkg/services/oauthtoken/oauthtokentest" "github.com/grafana/grafana/pkg/services/org" + "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig" + "github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" "github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/secrets" @@ -829,7 +831,8 @@ func getDatasourceProxiedRequest(t *testing.T, ctx *contextmodel.ReqContext, cfg features := featuremgmt.WithFeatures() quotaService := quotatest.New(false, nil) dsService, err := datasourceservice.ProvideService(nil, secretsService, secretsStore, cfg, features, acimpl.ProvideAccessControl(features), - &actest.FakePermissionsService{}, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + &actest.FakePermissionsService{}, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, + plugincontext.ProvideBaseService(cfg, pluginconfig.NewFakePluginRequestConfigProvider())) require.NoError(t, err) proxy, err := NewDataSourceProxy(ds, routes, ctx, "", cfg, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer, features) require.NoError(t, err) @@ -950,7 +953,8 @@ func runDatasourceAuthTest(t *testing.T, secretsService secrets.Service, secrets features := featuremgmt.WithFeatures() quotaService := quotatest.New(false, nil) dsService, err := datasourceservice.ProvideService(nil, secretsService, secretsStore, cfg, features, acimpl.ProvideAccessControl(features), - &actest.FakePermissionsService{}, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + &actest.FakePermissionsService{}, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, + plugincontext.ProvideBaseService(cfg, pluginconfig.NewFakePluginRequestConfigProvider())) require.NoError(t, err) proxy, err := NewDataSourceProxy(test.datasource, routes, ctx, "", &setting.Cfg{}, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer, features) require.NoError(t, err) @@ -1005,7 +1009,8 @@ func setupDSProxyTest(t *testing.T, ctx *contextmodel.ReqContext, ds *datasource secretsStore := secretskvs.NewSQLSecretsKVStore(dbtest.NewFakeDB(), secretsService, log.NewNopLogger()) features := featuremgmt.WithFeatures() dsService, err := datasourceservice.ProvideService(nil, secretsService, secretsStore, cfg, features, acimpl.ProvideAccessControl(features), - &actest.FakePermissionsService{}, quotatest.New(false, nil), &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + &actest.FakePermissionsService{}, quotatest.New(false, nil), &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, + plugincontext.ProvideBaseService(cfg, pluginconfig.NewFakePluginRequestConfigProvider())) require.NoError(t, err) tracer := tracing.InitializeTracerForTest() diff --git a/pkg/services/datasources/service/datasource.go b/pkg/services/datasources/service/datasource.go index ee8f61093b9..b6eef68eeb3 100644 --- a/pkg/services/datasources/service/datasource.go +++ b/pkg/services/datasources/service/datasource.go @@ -23,6 +23,8 @@ import ( "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/services/pluginsintegration/adapters" + "github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" "github.com/grafana/grafana/pkg/services/quota" "github.com/grafana/grafana/pkg/services/secrets" @@ -37,17 +39,18 @@ const ( ) type Service struct { - SQLStore Store - SecretsStore kvstore.SecretsKVStore - SecretsService secrets.Service - cfg *setting.Cfg - features featuremgmt.FeatureToggles - permissionsService accesscontrol.DatasourcePermissionsService - ac accesscontrol.AccessControl - logger log.Logger - db db.DB - pluginStore pluginstore.Store - pluginClient plugins.Client // access to everything + SQLStore Store + SecretsStore kvstore.SecretsKVStore + SecretsService secrets.Service + cfg *setting.Cfg + features featuremgmt.FeatureToggles + permissionsService accesscontrol.DatasourcePermissionsService + ac accesscontrol.AccessControl + logger log.Logger + db db.DB + pluginStore pluginstore.Store + pluginClient plugins.Client + basePluginContextProvider plugincontext.BasePluginContextProvider ptc proxyTransportCache } @@ -66,6 +69,7 @@ func ProvideService( db db.DB, secretsService secrets.Service, secretsStore kvstore.SecretsKVStore, cfg *setting.Cfg, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl, datasourcePermissionsService accesscontrol.DatasourcePermissionsService, quotaService quota.Service, pluginStore pluginstore.Store, pluginClient plugins.Client, + basePluginContextProvider plugincontext.BasePluginContextProvider, ) (*Service, error) { dslogger := log.New("datasources") store := &SqlStore{db: db, logger: dslogger, features: features} @@ -76,14 +80,15 @@ func ProvideService( ptc: proxyTransportCache{ cache: make(map[int64]cachedRoundTripper), }, - cfg: cfg, - features: features, - permissionsService: datasourcePermissionsService, - ac: ac, - logger: dslogger, - db: db, - pluginStore: pluginStore, - pluginClient: pluginClient, + cfg: cfg, + features: features, + permissionsService: datasourcePermissionsService, + ac: ac, + logger: dslogger, + db: db, + pluginStore: pluginStore, + pluginClient: pluginClient, + basePluginContextProvider: basePluginContextProvider, } ac.RegisterScopeAttributeResolver(NewNameScopeResolver(store)) @@ -216,10 +221,7 @@ func (s *Service) AddDataSource(ctx context.Context, cmd *datasources.AddDataSou return nil, fmt.Errorf("invalid jsonData") } - settings, err := s.prepareInstanceSettings(ctx, backend.PluginContext{ - OrgID: cmd.OrgID, - PluginID: cmd.Type, - }, &backend.DataSourceInstanceSettings{ + settings, err := s.prepareInstanceSettings(ctx, &backend.DataSourceInstanceSettings{ UID: cmd.UID, Name: cmd.Name, URL: cmd.URL, @@ -231,7 +233,7 @@ func (s *Service) AddDataSource(ctx context.Context, cmd *datasources.AddDataSou BasicAuthEnabled: cmd.BasicAuth, BasicAuthUser: cmd.BasicAuthUser, APIVersion: cmd.APIVersion, - }) + }, nil) if err != nil { return nil, err } @@ -296,7 +298,7 @@ func (s *Service) AddDataSource(ctx context.Context, cmd *datasources.AddDataSou } // This will valid validate the instance settings return a version that is safe to be saved -func (s *Service) prepareInstanceSettings(ctx context.Context, pluginContext backend.PluginContext, settings *backend.DataSourceInstanceSettings) (*backend.DataSourceInstanceSettings, error) { +func (s *Service) prepareInstanceSettings(ctx context.Context, settings *backend.DataSourceInstanceSettings, ds *datasources.DataSource) (*backend.DataSourceInstanceSettings, error) { operation := backend.AdmissionRequestCreate // First apply global validation rules -- these are required regardless which plugin we are talking to @@ -332,6 +334,15 @@ func (s *Service) prepareInstanceSettings(ctx context.Context, pluginContext bac return nil, err } + pluginContext := s.basePluginContextProvider.GetBasePluginContext(ctx, p, nil) + if ds != nil { + datasourceSettings, err := adapters.ModelToInstanceSettings(ds, s.decryptSecureJsonDataFn(ctx)) + if err != nil { + return nil, err + } + pluginContext.DataSourceInstanceSettings = datasourceSettings + } + req := &backend.AdmissionRequest{ Operation: backend.AdmissionRequestCreate, PluginContext: pluginContext, @@ -443,35 +454,10 @@ func (s *Service) DeleteDataSource(ctx context.Context, cmd *datasources.DeleteD }) } -func (s *Service) getPluginContext(ctx context.Context, orgID int64, pluginID string, ds *datasources.DataSource) (backend.PluginContext, error) { - var err error - if ds == nil { - return backend.PluginContext{ - OrgID: orgID, - PluginID: pluginID, - }, err +func (s *Service) decryptSecureJsonDataFn(ctx context.Context) func(ds *datasources.DataSource) (map[string]string, error) { + return func(ds *datasources.DataSource) (map[string]string, error) { + return s.DecryptedValues(ctx, ds) } - pctx := backend.PluginContext{ - OrgID: orgID, - PluginID: pluginID, - DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{ - UID: ds.UID, - Type: pluginID, - Name: ds.Name, - URL: ds.URL, - Database: ds.Database, - BasicAuthEnabled: ds.BasicAuth, - BasicAuthUser: ds.BasicAuthUser, - Updated: ds.Updated, - APIVersion: ds.APIVersion, - User: ds.User, - }, - } - pctx.DataSourceInstanceSettings.JSONData, err = ds.JsonData.ToDB() - if err == nil && len(ds.SecureJsonData) > 0 { - pctx.DataSourceInstanceSettings.DecryptedSecureJSONData, err = s.DecryptedValues(ctx, ds) - } - return pctx, err } func (s *Service) UpdateDataSource(ctx context.Context, cmd *datasources.UpdateDataSourceCommand) (*datasources.DataSource, error) { @@ -494,12 +480,8 @@ func (s *Service) UpdateDataSource(ctx context.Context, cmd *datasources.UpdateD if err != nil { return fmt.Errorf("invalid jsonData") } - pctx, err := s.getPluginContext(ctx, cmd.OrgID, cmd.Type, dataSource) - if err != nil { - return err - } - settings, err := s.prepareInstanceSettings(ctx, pctx, + settings, err := s.prepareInstanceSettings(ctx, &backend.DataSourceInstanceSettings{ UID: cmd.UID, Name: cmd.Name, @@ -513,7 +495,7 @@ func (s *Service) UpdateDataSource(ctx context.Context, cmd *datasources.UpdateD BasicAuthUser: cmd.BasicAuthUser, APIVersion: cmd.APIVersion, Updated: time.Now(), - }) + }, dataSource) if err != nil { return err } diff --git a/pkg/services/datasources/service/datasource_test.go b/pkg/services/datasources/service/datasource_test.go index ce7acfe782d..bf811c43e8d 100644 --- a/pkg/services/datasources/service/datasource_test.go +++ b/pkg/services/datasources/service/datasource_test.go @@ -27,6 +27,8 @@ import ( acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig" + "github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" "github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/secrets" @@ -82,7 +84,7 @@ func TestService_AddDataSource(t *testing.T) { ValidateAdmissionFunc: dsplugin.ValidateAdmission, MutateAdmissionFunc: dsplugin.MutateAdmission, ConvertObjectFunc: dsplugin.ConvertObject, - }) + }, plugincontext.ProvideBaseService(cfg, pluginconfig.NewFakePluginRequestConfigProvider())) require.NoError(t, err) cmd := &datasources.AddDataSourceCommand{ @@ -205,7 +207,7 @@ func TestService_UpdateDataSource(t *testing.T) { secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) mockPermission := acmock.NewMockedPermissionsService() - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), actest.FakeAccessControl{}, mockPermission, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), actest.FakeAccessControl{}, mockPermission, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) cmd := &datasources.UpdateDataSourceCommand{ @@ -234,7 +236,8 @@ func TestService_UpdateDataSource(t *testing.T) { }, }, }, - }, &pluginfakes.FakePluginClient{}) + }, &pluginfakes.FakePluginClient{}, + plugincontext.ProvideBaseService(cfg, pluginconfig.NewFakePluginRequestConfigProvider())) require.NoError(t, err) // First add the datasource @@ -273,7 +276,7 @@ func TestService_UpdateDataSource(t *testing.T) { secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) mockPermission := acmock.NewMockedPermissionsService() - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), actest.FakeAccessControl{}, mockPermission, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), actest.FakeAccessControl{}, mockPermission, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) mockPermission.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil) @@ -300,7 +303,7 @@ func TestService_UpdateDataSource(t *testing.T) { secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) mockPermission := acmock.NewMockedPermissionsService() - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), actest.FakeAccessControl{}, mockPermission, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), actest.FakeAccessControl{}, mockPermission, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) mockPermission.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil) @@ -333,7 +336,7 @@ func TestService_UpdateDataSource(t *testing.T) { secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) mockPermission := acmock.NewMockedPermissionsService() - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), actest.FakeAccessControl{}, mockPermission, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), actest.FakeAccessControl{}, mockPermission, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) mockPermission.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil) @@ -378,7 +381,7 @@ func TestService_UpdateDataSource(t *testing.T) { quotaService := quotatest.New(false, nil) mockPermission := acmock.NewMockedPermissionsService() dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), actest.FakeAccessControl{}, - mockPermission, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + mockPermission, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) mockPermission.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil) @@ -640,7 +643,7 @@ func TestService_GetHttpTransport(t *testing.T) { secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) rt1, err := dsService.GetHTTPTransport(context.Background(), &ds, provider) @@ -677,7 +680,7 @@ func TestService_GetHttpTransport(t *testing.T) { secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) ds := datasources.DataSource{ @@ -728,7 +731,7 @@ func TestService_GetHttpTransport(t *testing.T) { secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) ds := datasources.DataSource{ @@ -776,7 +779,7 @@ func TestService_GetHttpTransport(t *testing.T) { secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) ds := datasources.DataSource{ @@ -832,7 +835,7 @@ func TestService_GetHttpTransport(t *testing.T) { secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) ds := datasources.DataSource{ @@ -867,7 +870,7 @@ func TestService_GetHttpTransport(t *testing.T) { secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) ds := datasources.DataSource{ @@ -936,7 +939,7 @@ func TestService_GetHttpTransport(t *testing.T) { secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) ds := datasources.DataSource{ @@ -1015,7 +1018,7 @@ func TestService_GetHttpTransport(t *testing.T) { secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) ds := datasources.DataSource{ @@ -1036,7 +1039,7 @@ func TestService_getProxySettings(t *testing.T) { secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, &setting.Cfg{}, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, &setting.Cfg{}, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) t.Run("Should default to disabled", func(t *testing.T) { @@ -1132,7 +1135,7 @@ func TestService_getTimeout(t *testing.T) { secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) for _, tc := range testCases { @@ -1155,7 +1158,7 @@ func TestService_GetDecryptedValues(t *testing.T) { secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, nil, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, nil, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) jsonData := map[string]string{ @@ -1183,7 +1186,7 @@ func TestService_GetDecryptedValues(t *testing.T) { secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, nil, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, nil, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) jsonData := map[string]string{ @@ -1207,7 +1210,7 @@ func TestDataSource_CustomHeaders(t *testing.T) { secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) quotaService := quotatest.New(false, nil) - dsService, err := ProvideService(sqlStore, secretsService, secretsStore, nil, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + dsService, err := ProvideService(sqlStore, secretsService, secretsStore, nil, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, nil) require.NoError(t, err) dsService.cfg = setting.NewCfg() diff --git a/pkg/services/pluginsintegration/plugincontext/base_plugincontext.go b/pkg/services/pluginsintegration/plugincontext/base_plugincontext.go new file mode 100644 index 00000000000..bf4c1f4985c --- /dev/null +++ b/pkg/services/pluginsintegration/plugincontext/base_plugincontext.go @@ -0,0 +1,62 @@ +package plugincontext + +import ( + "context" + "runtime" + + "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/grafana/grafana-plugin-sdk-go/backend/useragent" + "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/services/auth/identity" + "github.com/grafana/grafana/pkg/services/pluginsintegration/adapters" + "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig" + "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" + "github.com/grafana/grafana/pkg/setting" +) + +type BasePluginContextProvider interface { + // GetBasePluginContext returns a plugin context for the given plugin and user. + // It does not add DatasourceInstaceSettings or AppInstanceSettings + GetBasePluginContext(ctx context.Context, plugin pluginstore.Plugin, user identity.Requester) backend.PluginContext +} + +func ProvideBaseService(cfg *setting.Cfg, pluginRequestConfigProvider pluginconfig.PluginRequestConfigProvider) *BaseProvider { + return newBaseProvider(cfg, pluginRequestConfigProvider) +} + +func newBaseProvider(cfg *setting.Cfg, pluginRequestConfigProvider pluginconfig.PluginRequestConfigProvider) *BaseProvider { + return &BaseProvider{ + cfg: cfg, + pluginRequestConfigProvider: pluginRequestConfigProvider, + logger: log.New("base.plugin.context"), + } +} + +type BaseProvider struct { + cfg *setting.Cfg + pluginRequestConfigProvider pluginconfig.PluginRequestConfigProvider + logger log.Logger +} + +func (p *BaseProvider) GetBasePluginContext(ctx context.Context, plugin pluginstore.Plugin, user identity.Requester) backend.PluginContext { + pCtx := backend.PluginContext{ + PluginID: plugin.ID, + PluginVersion: plugin.Info.Version, + APIVersion: plugin.APIVersion, + } + if user != nil && !user.IsNil() { + pCtx.OrgID = user.GetOrgID() + pCtx.User = adapters.BackendUserFromSignedInUser(user) + } + + settings := p.pluginRequestConfigProvider.PluginRequestConfig(ctx, plugin.ID, plugin.ExternalService) + pCtx.GrafanaConfig = backend.NewGrafanaCfg(settings) + + ua, err := useragent.New(p.cfg.BuildVersion, runtime.GOOS, runtime.GOARCH) + if err != nil { + p.logger.Warn("Could not create user agent", "error", err) + } + pCtx.UserAgent = ua + + return pCtx +} diff --git a/pkg/services/pluginsintegration/plugincontext/plugincontext.go b/pkg/services/pluginsintegration/plugincontext/plugincontext.go index b7c5f10b187..21cdbf12b8e 100644 --- a/pkg/services/pluginsintegration/plugincontext/plugincontext.go +++ b/pkg/services/pluginsintegration/plugincontext/plugincontext.go @@ -5,11 +5,9 @@ import ( "encoding/json" "errors" "fmt" - "runtime" "time" "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana-plugin-sdk-go/backend/useragent" "github.com/grafana/grafana/pkg/infra/appcontext" "github.com/grafana/grafana/pkg/infra/localcache" @@ -33,26 +31,24 @@ func ProvideService(cfg *setting.Cfg, cacheService *localcache.CacheService, plu dataSourceCache datasources.CacheService, dataSourceService datasources.DataSourceService, pluginSettingsService pluginsettings.Service, pluginRequestConfigProvider pluginconfig.PluginRequestConfigProvider) *Provider { return &Provider{ - cfg: cfg, - cacheService: cacheService, - pluginStore: pluginStore, - dataSourceCache: dataSourceCache, - dataSourceService: dataSourceService, - pluginSettingsService: pluginSettingsService, - pluginRequestConfigProvider: pluginRequestConfigProvider, - logger: log.New("plugin.context"), + BaseProvider: newBaseProvider(cfg, pluginRequestConfigProvider), + cacheService: cacheService, + pluginStore: pluginStore, + dataSourceCache: dataSourceCache, + dataSourceService: dataSourceService, + pluginSettingsService: pluginSettingsService, + logger: log.New("plugin.context"), } } type Provider struct { - cfg *setting.Cfg - pluginRequestConfigProvider pluginconfig.PluginRequestConfigProvider - cacheService *localcache.CacheService - pluginStore pluginstore.Store - dataSourceCache datasources.CacheService - dataSourceService datasources.DataSourceService - pluginSettingsService pluginsettings.Service - logger log.Logger + *BaseProvider + cacheService *localcache.CacheService + pluginStore pluginstore.Store + dataSourceCache datasources.CacheService + dataSourceService datasources.DataSourceService + pluginSettingsService pluginsettings.Service + logger log.Logger } // Get will retrieve plugin context by the provided pluginID and orgID. @@ -65,16 +61,7 @@ func (p *Provider) Get(ctx context.Context, pluginID string, user identity.Reque return backend.PluginContext{}, plugins.ErrPluginNotRegistered } - pCtx := backend.PluginContext{ - PluginID: plugin.ID, - PluginVersion: plugin.Info.Version, - APIVersion: plugin.APIVersion, - } - if user != nil && !user.IsNil() { - pCtx.OrgID = user.GetOrgID() - pCtx.User = adapters.BackendUserFromSignedInUser(user) - } - + pCtx := p.GetBasePluginContext(ctx, plugin, user) if plugin.IsApp() { appSettings, err := p.appInstanceSettings(ctx, pluginID, orgID) if err != nil { @@ -83,15 +70,6 @@ func (p *Provider) Get(ctx context.Context, pluginID string, user identity.Reque pCtx.AppInstanceSettings = appSettings } - settings := p.pluginRequestConfigProvider.PluginRequestConfig(ctx, pluginID, plugin.ExternalService) - pCtx.GrafanaConfig = backend.NewGrafanaCfg(settings) - - ua, err := useragent.New(p.cfg.BuildVersion, runtime.GOOS, runtime.GOARCH) - if err != nil { - p.logger.Warn("Could not create user agent", "error", err) - } - pCtx.UserAgent = ua - return pCtx, nil } @@ -105,15 +83,7 @@ func (p *Provider) GetWithDataSource(ctx context.Context, pluginID string, user return backend.PluginContext{}, plugins.ErrPluginNotRegistered } - pCtx := backend.PluginContext{ - PluginID: plugin.ID, - PluginVersion: plugin.Info.Version, - APIVersion: plugin.APIVersion, - } - if user != nil && !user.IsNil() { - pCtx.OrgID = user.GetOrgID() - pCtx.User = adapters.BackendUserFromSignedInUser(user) - } + pCtx := p.GetBasePluginContext(ctx, plugin, user) datasourceSettings, err := adapters.ModelToInstanceSettings(ds, p.decryptSecureJsonDataFn(ctx)) if err != nil { @@ -121,15 +91,6 @@ func (p *Provider) GetWithDataSource(ctx context.Context, pluginID string, user } pCtx.DataSourceInstanceSettings = datasourceSettings - settings := p.pluginRequestConfigProvider.PluginRequestConfig(ctx, pluginID, plugin.ExternalService) - pCtx.GrafanaConfig = backend.NewGrafanaCfg(settings) - - ua, err := useragent.New(p.cfg.BuildVersion, runtime.GOOS, runtime.GOARCH) - if err != nil { - p.logger.Warn("Could not create user agent", "error", err) - } - pCtx.UserAgent = ua - return pCtx, nil } @@ -158,27 +119,9 @@ func (p *Provider) PluginContextForDataSource(ctx context.Context, datasourceSet if err != nil { return backend.PluginContext{}, err } - pCtx := backend.PluginContext{ - PluginID: plugin.ID, - PluginVersion: plugin.Info.Version, - APIVersion: plugin.APIVersion, - } - if user != nil && !user.IsNil() { - pCtx.OrgID = user.GetOrgID() - pCtx.User = adapters.BackendUserFromSignedInUser(user) - } - + pCtx := p.GetBasePluginContext(ctx, plugin, user) pCtx.DataSourceInstanceSettings = datasourceSettings - settings := p.pluginRequestConfigProvider.PluginRequestConfig(ctx, pluginID, plugin.ExternalService) - pCtx.GrafanaConfig = backend.NewGrafanaCfg(settings) - - ua, err := useragent.New(p.cfg.BuildVersion, runtime.GOOS, runtime.GOARCH) - if err != nil { - p.logger.Warn("Could not create user agent", "error", err) - } - pCtx.UserAgent = ua - return pCtx, nil } diff --git a/pkg/services/pluginsintegration/pluginsintegration.go b/pkg/services/pluginsintegration/pluginsintegration.go index b0987027ac1..6963438dd8a 100644 --- a/pkg/services/pluginsintegration/pluginsintegration.go +++ b/pkg/services/pluginsintegration/pluginsintegration.go @@ -43,6 +43,7 @@ import ( "github.com/grafana/grafana/pkg/services/pluginsintegration/loader" "github.com/grafana/grafana/pkg/services/pluginsintegration/pipeline" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig" + "github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginexternal" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings" @@ -120,6 +121,8 @@ var WireSet = wire.NewSet( renderer.ProvideService, wire.Bind(new(rendering.PluginManager), new(*renderer.Manager)), pluginexternal.ProvideService, + plugincontext.ProvideBaseService, + wire.Bind(new(plugincontext.BasePluginContextProvider), new(*plugincontext.BaseProvider)), ) // WireExtensionSet provides a wire.ProviderSet of plugin providers that can be diff --git a/pkg/services/quota/quotaimpl/quota_test.go b/pkg/services/quota/quotaimpl/quota_test.go index 48eecb50a50..4b4696a5bf5 100644 --- a/pkg/services/quota/quotaimpl/quota_test.go +++ b/pkg/services/quota/quotaimpl/quota_test.go @@ -34,6 +34,8 @@ import ( ngalertfakes "github.com/grafana/grafana/pkg/services/ngalert/tests/fakes" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org/orgimpl" + "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig" + "github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" "github.com/grafana/grafana/pkg/services/quota" "github.com/grafana/grafana/pkg/services/quota/quotatest" @@ -486,7 +488,8 @@ func setupEnv(t *testing.T, sqlStore db.DB, cfg *setting.Cfg, b bus.Bus, quotaSe secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsStore := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger")) _, err = dsservice.ProvideService(sqlStore, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService(), - quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, plugincontext. + ProvideBaseService(cfg, pluginconfig.NewFakePluginRequestConfigProvider())) require.NoError(t, err) m := metrics.NewNGAlert(prometheus.NewRegistry()) diff --git a/pkg/services/secrets/kvstore/migrations/datasource_mig_test.go b/pkg/services/secrets/kvstore/migrations/datasource_mig_test.go index 94568dc08d7..f22d2456eb7 100644 --- a/pkg/services/secrets/kvstore/migrations/datasource_mig_test.go +++ b/pkg/services/secrets/kvstore/migrations/datasource_mig_test.go @@ -15,6 +15,8 @@ import ( "github.com/grafana/grafana/pkg/services/datasources" dsservice "github.com/grafana/grafana/pkg/services/datasources/service" "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig" + "github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" "github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/secrets/fakes" @@ -38,7 +40,8 @@ func SetupTestDataSourceSecretMigrationService(t *testing.T, sqlStore db.DB, kvS secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) quotaService := quotatest.New(false, nil) dsService, err := dsservice.ProvideService(sqlStore, secretsService, secretsStore, cfg, features, acmock.New(), - acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + acmock.NewMockedPermissionsService(), quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, + plugincontext.ProvideBaseService(cfg, pluginconfig.NewFakePluginRequestConfigProvider())) require.NoError(t, err) migService := ProvideDataSourceMigrationService(dsService, kvStore, features) return migService diff --git a/pkg/tsdb/legacydata/service/service_test.go b/pkg/tsdb/legacydata/service/service_test.go index 974c2453c7f..f9dd8b4ff3d 100644 --- a/pkg/tsdb/legacydata/service/service_test.go +++ b/pkg/tsdb/legacydata/service/service_test.go @@ -50,7 +50,8 @@ func TestHandleRequest(t *testing.T) { quotaService := quotatest.New(false, nil) dsCache := datasourceservice.ProvideCacheService(localcache.ProvideService(), sqlStore, guardian.ProvideGuardian()) dsService, err := datasourceservice.ProvideService(nil, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), - acmock.New(), datasourcePermissions, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}) + acmock.New(), datasourcePermissions, quotaService, &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{}, + plugincontext.ProvideBaseService(cfg, pluginconfig.NewFakePluginRequestConfigProvider())) require.NoError(t, err) pCtxProvider := plugincontext.ProvideService(cfg, localcache.ProvideService(), &pluginstore.FakePluginStore{