Datasource: Fixes storing of secureJSONData when creating/updating datasource (#45290)

Fixes an issue introduced by #44987 where bus dispatch was replaced by calling sqlstore 
directly instead of the datasource service.

Fixes #45273
pull/45326/head
Marcus Efraimsson 4 years ago committed by GitHub
parent 334ee9c4a7
commit 6a776c78d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 26
      pkg/api/datasources.go
  2. 80
      pkg/api/datasources_test.go
  3. 4
      pkg/api/http_server.go
  4. 11
      pkg/api/pluginproxy/ds_proxy.go
  5. 114
      pkg/api/pluginproxy/ds_proxy_test.go
  6. 4
      pkg/server/wire.go
  7. 5
      pkg/server/wireexts_oss.go
  8. 10
      pkg/services/datasourceproxy/datasourceproxy.go
  9. 62
      pkg/services/datasources/datasources.go
  10. 9
      pkg/services/datasources/log.go
  11. 14
      pkg/services/datasources/service/cache_service.go
  12. 4
      pkg/services/datasources/service/datasource_service.go
  13. 2
      pkg/services/datasources/service/datasource_service_test.go
  14. 5
      pkg/tsdb/legacydata/service/service.go
  15. 4
      pkg/tsdb/legacydata/service/service_test.go

@ -27,7 +27,7 @@ var datasourcesLogger = log.New("datasources")
func (hs *HTTPServer) GetDataSources(c *models.ReqContext) response.Response { func (hs *HTTPServer) GetDataSources(c *models.ReqContext) response.Response {
query := models.GetDataSourcesQuery{OrgId: c.OrgId, DataSourceLimit: hs.Cfg.DataSourceLimit} query := models.GetDataSourcesQuery{OrgId: c.OrgId, DataSourceLimit: hs.Cfg.DataSourceLimit}
if err := hs.SQLStore.GetDataSources(c.Req.Context(), &query); err != nil { if err := hs.DataSourcesService.GetDataSources(c.Req.Context(), &query); err != nil {
return response.Error(500, "Failed to query datasources", err) return response.Error(500, "Failed to query datasources", err)
} }
@ -98,7 +98,7 @@ func (hs *HTTPServer) GetDataSourceById(c *models.ReqContext) response.Response
OrgId: c.OrgId, OrgId: c.OrgId,
} }
if err := hs.SQLStore.GetDataSource(c.Req.Context(), &query); err != nil { if err := hs.DataSourcesService.GetDataSource(c.Req.Context(), &query); err != nil {
if errors.Is(err, models.ErrDataSourceNotFound) { if errors.Is(err, models.ErrDataSourceNotFound) {
return response.Error(404, "Data source not found", nil) return response.Error(404, "Data source not found", nil)
} }
@ -149,7 +149,7 @@ func (hs *HTTPServer) DeleteDataSourceById(c *models.ReqContext) response.Respon
cmd := &models.DeleteDataSourceCommand{ID: id, OrgID: c.OrgId} cmd := &models.DeleteDataSourceCommand{ID: id, OrgID: c.OrgId}
err = hs.SQLStore.DeleteDataSource(c.Req.Context(), cmd) err = hs.DataSourcesService.DeleteDataSource(c.Req.Context(), cmd)
if err != nil { if err != nil {
return response.Error(500, "Failed to delete datasource", err) return response.Error(500, "Failed to delete datasource", err)
} }
@ -209,7 +209,7 @@ func (hs *HTTPServer) DeleteDataSourceByUID(c *models.ReqContext) response.Respo
cmd := &models.DeleteDataSourceCommand{UID: uid, OrgID: c.OrgId} cmd := &models.DeleteDataSourceCommand{UID: uid, OrgID: c.OrgId}
err = hs.SQLStore.DeleteDataSource(c.Req.Context(), cmd) err = hs.DataSourcesService.DeleteDataSource(c.Req.Context(), cmd)
if err != nil { if err != nil {
return response.Error(500, "Failed to delete datasource", err) return response.Error(500, "Failed to delete datasource", err)
} }
@ -231,7 +231,7 @@ func (hs *HTTPServer) DeleteDataSourceByName(c *models.ReqContext) response.Resp
} }
getCmd := &models.GetDataSourceQuery{Name: name, OrgId: c.OrgId} getCmd := &models.GetDataSourceQuery{Name: name, OrgId: c.OrgId}
if err := hs.SQLStore.GetDataSource(c.Req.Context(), getCmd); err != nil { if err := hs.DataSourcesService.GetDataSource(c.Req.Context(), getCmd); err != nil {
if errors.Is(err, models.ErrDataSourceNotFound) { if errors.Is(err, models.ErrDataSourceNotFound) {
return response.Error(404, "Data source not found", nil) return response.Error(404, "Data source not found", nil)
} }
@ -243,7 +243,7 @@ func (hs *HTTPServer) DeleteDataSourceByName(c *models.ReqContext) response.Resp
} }
cmd := &models.DeleteDataSourceCommand{Name: name, OrgID: c.OrgId} cmd := &models.DeleteDataSourceCommand{Name: name, OrgID: c.OrgId}
err := hs.SQLStore.DeleteDataSource(c.Req.Context(), cmd) err := hs.DataSourcesService.DeleteDataSource(c.Req.Context(), cmd)
if err != nil { if err != nil {
return response.Error(500, "Failed to delete datasource", err) return response.Error(500, "Failed to delete datasource", err)
} }
@ -279,7 +279,7 @@ func (hs *HTTPServer) AddDataSource(c *models.ReqContext) response.Response {
} }
} }
if err := hs.SQLStore.AddDataSource(c.Req.Context(), &cmd); err != nil { if err := hs.DataSourcesService.AddDataSource(c.Req.Context(), &cmd); err != nil {
if errors.Is(err, models.ErrDataSourceNameExists) || errors.Is(err, models.ErrDataSourceUidExists) { if errors.Is(err, models.ErrDataSourceNameExists) || errors.Is(err, models.ErrDataSourceUidExists) {
return response.Error(409, err.Error(), err) return response.Error(409, err.Error(), err)
} }
@ -329,7 +329,7 @@ func (hs *HTTPServer) UpdateDataSource(c *models.ReqContext) response.Response {
return response.Error(500, "Failed to update datasource", err) return response.Error(500, "Failed to update datasource", err)
} }
err = hs.SQLStore.UpdateDataSource(c.Req.Context(), &cmd) err = hs.DataSourcesService.UpdateDataSource(c.Req.Context(), &cmd)
if err != nil { if err != nil {
if errors.Is(err, models.ErrDataSourceUpdatingOldVersion) { if errors.Is(err, models.ErrDataSourceUpdatingOldVersion) {
return response.Error(409, "Datasource has already been updated by someone else. Please reload and try again", err) return response.Error(409, "Datasource has already been updated by someone else. Please reload and try again", err)
@ -342,7 +342,7 @@ func (hs *HTTPServer) UpdateDataSource(c *models.ReqContext) response.Response {
OrgId: c.OrgId, OrgId: c.OrgId,
} }
if err := hs.SQLStore.GetDataSource(c.Req.Context(), &query); err != nil { if err := hs.DataSourcesService.GetDataSource(c.Req.Context(), &query); err != nil {
if errors.Is(err, models.ErrDataSourceNotFound) { if errors.Is(err, models.ErrDataSourceNotFound) {
return response.Error(404, "Data source not found", nil) return response.Error(404, "Data source not found", nil)
} }
@ -394,7 +394,7 @@ func (hs *HTTPServer) getRawDataSourceById(ctx context.Context, id int64, orgID
OrgId: orgID, OrgId: orgID,
} }
if err := hs.SQLStore.GetDataSource(ctx, &query); err != nil { if err := hs.DataSourcesService.GetDataSource(ctx, &query); err != nil {
return nil, err return nil, err
} }
@ -407,7 +407,7 @@ func (hs *HTTPServer) getRawDataSourceByUID(ctx context.Context, uid string, org
OrgId: orgID, OrgId: orgID,
} }
if err := hs.SQLStore.GetDataSource(ctx, &query); err != nil { if err := hs.DataSourcesService.GetDataSource(ctx, &query); err != nil {
return nil, err return nil, err
} }
@ -418,7 +418,7 @@ func (hs *HTTPServer) getRawDataSourceByUID(ctx context.Context, uid string, org
func (hs *HTTPServer) GetDataSourceByName(c *models.ReqContext) response.Response { func (hs *HTTPServer) GetDataSourceByName(c *models.ReqContext) response.Response {
query := models.GetDataSourceQuery{Name: web.Params(c.Req)[":name"], OrgId: c.OrgId} query := models.GetDataSourceQuery{Name: web.Params(c.Req)[":name"], OrgId: c.OrgId}
if err := hs.SQLStore.GetDataSource(c.Req.Context(), &query); err != nil { if err := hs.DataSourcesService.GetDataSource(c.Req.Context(), &query); err != nil {
if errors.Is(err, models.ErrDataSourceNotFound) { if errors.Is(err, models.ErrDataSourceNotFound) {
return response.Error(404, "Data source not found", nil) return response.Error(404, "Data source not found", nil)
} }
@ -438,7 +438,7 @@ func (hs *HTTPServer) GetDataSourceByName(c *models.ReqContext) response.Respons
func (hs *HTTPServer) GetDataSourceIdByName(c *models.ReqContext) response.Response { func (hs *HTTPServer) GetDataSourceIdByName(c *models.ReqContext) response.Response {
query := models.GetDataSourceQuery{Name: web.Params(c.Req)[":name"], OrgId: c.OrgId} query := models.GetDataSourceQuery{Name: web.Params(c.Req)[":name"], OrgId: c.OrgId}
if err := hs.SQLStore.GetDataSource(c.Req.Context(), &query); err != nil { if err := hs.DataSourcesService.GetDataSource(c.Req.Context(), &query); err != nil {
if errors.Is(err, models.ErrDataSourceNotFound) { if errors.Is(err, models.ErrDataSourceNotFound) {
return response.Error(404, "Data source not found", nil) return response.Error(404, "Data source not found", nil)
} }

@ -2,6 +2,7 @@ package api
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
@ -13,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore" "github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -36,14 +38,15 @@ func TestDataSourcesProxy_userLoggedIn(t *testing.T) {
{Name: "BBB"}, {Name: "BBB"},
{Name: "aaa"}, {Name: "aaa"},
} }
mockSQLStore.ExpectedDatasources = ds
mockDatasourcePermissionService.dsResult = ds mockDatasourcePermissionService.dsResult = ds
// handler func being tested // handler func being tested
hs := &HTTPServer{ hs := &HTTPServer{
Cfg: setting.NewCfg(), Cfg: setting.NewCfg(),
pluginStore: &fakePluginStore{}, pluginStore: &fakePluginStore{},
SQLStore: mockSQLStore, DataSourcesService: &dataSourcesServiceMock{
expectedDatasources: ds,
},
DatasourcePermissionsService: mockDatasourcePermissionService, DatasourcePermissionsService: mockDatasourcePermissionService,
} }
sc.handlerFunc = hs.GetDataSources sc.handlerFunc = hs.GetDataSources
@ -76,7 +79,7 @@ func TestDataSourcesProxy_userLoggedIn(t *testing.T) {
func TestAddDataSource_InvalidURL(t *testing.T) { func TestAddDataSource_InvalidURL(t *testing.T) {
sc := setupScenarioContext(t, "/api/datasources") sc := setupScenarioContext(t, "/api/datasources")
hs := &HTTPServer{ hs := &HTTPServer{
SQLStore: mockstore.NewSQLStoreMock(), DataSourcesService: &dataSourcesServiceMock{},
} }
sc.m.Post(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response { sc.m.Post(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response {
@ -99,10 +102,10 @@ func TestAddDataSource_URLWithoutProtocol(t *testing.T) {
const name = "Test" const name = "Test"
const url = "localhost:5432" const url = "localhost:5432"
mockSQLStore := mockstore.NewSQLStoreMock()
mockSQLStore.ExpectedDatasource = &models.DataSource{}
hs := &HTTPServer{ hs := &HTTPServer{
SQLStore: mockSQLStore, DataSourcesService: &dataSourcesServiceMock{
expectedDatasource: &models.DataSource{},
},
} }
sc := setupScenarioContext(t, "/api/datasources") sc := setupScenarioContext(t, "/api/datasources")
@ -125,7 +128,7 @@ func TestAddDataSource_URLWithoutProtocol(t *testing.T) {
// Updating data sources with invalid URLs should lead to an error. // Updating data sources with invalid URLs should lead to an error.
func TestUpdateDataSource_InvalidURL(t *testing.T) { func TestUpdateDataSource_InvalidURL(t *testing.T) {
hs := &HTTPServer{ hs := &HTTPServer{
SQLStore: mockstore.NewSQLStoreMock(), DataSourcesService: &dataSourcesServiceMock{},
} }
sc := setupScenarioContext(t, "/api/datasources/1234") sc := setupScenarioContext(t, "/api/datasources/1234")
@ -149,12 +152,11 @@ func TestUpdateDataSource_URLWithoutProtocol(t *testing.T) {
const name = "Test" const name = "Test"
const url = "localhost:5432" const url = "localhost:5432"
mockSQLStore := mockstore.NewSQLStoreMock()
hs := &HTTPServer{ hs := &HTTPServer{
SQLStore: mockSQLStore, DataSourcesService: &dataSourcesServiceMock{
expectedDatasource: &models.DataSource{},
},
} }
// Stub handler
mockSQLStore.ExpectedDatasource = &models.DataSource{}
sc := setupScenarioContext(t, "/api/datasources/1234") sc := setupScenarioContext(t, "/api/datasources/1234")
@ -204,8 +206,9 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
return bytes.NewReader(s) return bytes.NewReader(s)
} }
sqlStore := mockstore.NewSQLStoreMock() dsServiceMock := &dataSourcesServiceMock{
sqlStore.ExpectedDatasource = &testDatasource expectedDatasource: &testDatasource,
}
dsPermissionService := newMockDatasourcePermissionService() dsPermissionService := newMockDatasourcePermissionService()
dsPermissionService.dsResult = []*models.DataSource{ dsPermissionService.dsResult = []*models.DataSource{
&testDatasource, &testDatasource,
@ -500,14 +503,13 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
sc, hs := setupAccessControlScenarioContext(t, cfg, test.url, test.permissions) sc, hs := setupAccessControlScenarioContext(t, cfg, test.url, test.permissions)
// mock sqlStore and datasource permission service // mock sqlStore and datasource permission service
sqlStore.ExpectedError = test.expectedSQLError dsServiceMock.expectedError = test.expectedSQLError
sqlStore.ExpectedDatasource = test.expectedDS dsServiceMock.expectedDatasource = test.expectedDS
dsPermissionService.dsResult = []*models.DataSource{test.expectedDS} dsPermissionService.dsResult = []*models.DataSource{test.expectedDS}
if test.expectedDS == nil { if test.expectedDS == nil {
dsPermissionService.dsResult = nil dsPermissionService.dsResult = nil
} }
sc.sqlStore = sqlStore hs.DataSourcesService = dsServiceMock
hs.SQLStore = sqlStore
hs.DatasourcePermissionsService = dsPermissionService hs.DatasourcePermissionsService = dsPermissionService
// Create a middleware to pretend user is logged in // Create a middleware to pretend user is logged in
@ -539,3 +541,43 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
}) })
} }
} }
type dataSourcesServiceMock struct {
datasources.DataSourceService
expectedDatasources []*models.DataSource
expectedDatasource *models.DataSource
expectedError error
}
func (m *dataSourcesServiceMock) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error {
query.Result = m.expectedDatasource
return m.expectedError
}
func (m *dataSourcesServiceMock) GetDataSources(ctx context.Context, query *models.GetDataSourcesQuery) error {
query.Result = m.expectedDatasources
return m.expectedError
}
func (m *dataSourcesServiceMock) GetDataSourcesByType(ctx context.Context, query *models.GetDataSourcesByTypeQuery) error {
return m.expectedError
}
func (m *dataSourcesServiceMock) GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error {
return m.expectedError
}
func (m *dataSourcesServiceMock) DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSourceCommand) error {
return m.expectedError
}
func (m *dataSourcesServiceMock) AddDataSource(ctx context.Context, cmd *models.AddDataSourceCommand) error {
cmd.Result = m.expectedDatasource
return m.expectedError
}
func (m *dataSourcesServiceMock) UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSourceCommand) error {
cmd.Result = m.expectedDatasource
return m.expectedError
}

@ -117,7 +117,7 @@ type HTTPServer struct {
Listener net.Listener Listener net.Listener
EncryptionService encryption.Internal EncryptionService encryption.Internal
SecretsService secrets.Service SecretsService secrets.Service
DataSourcesService *datasources.Service DataSourcesService datasources.DataSourceService
cleanUpService *cleanup.CleanUpService cleanUpService *cleanup.CleanUpService
tracer tracing.Tracer tracer tracing.Tracer
grafanaUpdateChecker *updatechecker.GrafanaService grafanaUpdateChecker *updatechecker.GrafanaService
@ -155,7 +155,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
quotaService *quota.QuotaService, socialService social.Service, tracer tracing.Tracer, quotaService *quota.QuotaService, socialService social.Service, tracer tracing.Tracer,
encryptionService encryption.Internal, grafanaUpdateChecker *updatechecker.GrafanaService, encryptionService encryption.Internal, grafanaUpdateChecker *updatechecker.GrafanaService,
pluginsUpdateChecker *updatechecker.PluginsService, searchUsersService searchusers.Service, pluginsUpdateChecker *updatechecker.PluginsService, searchUsersService searchusers.Service,
dataSourcesService *datasources.Service, secretsService secrets.Service, queryDataService *query.Service, dataSourcesService datasources.DataSourceService, secretsService secrets.Service, queryDataService *query.Service,
ldapGroups ldap.Groups, teamGuardian teamguardian.TeamGuardian, serviceaccountsService serviceaccounts.Service, ldapGroups ldap.Groups, teamGuardian teamguardian.TeamGuardian, serviceaccountsService serviceaccounts.Service,
authInfoService login.AuthInfoService, resourcePermissionServices *resourceservices.ResourceServices, authInfoService login.AuthInfoService, resourcePermissionServices *resourceservices.ResourceServices,
notificationService *notifications.NotificationService, datasourcePermissionsService DatasourcePermissionsService) (*HTTPServer, error) { notificationService *notifications.NotificationService, datasourcePermissionsService DatasourcePermissionsService) (*HTTPServer, error) {

@ -21,6 +21,7 @@ import (
"github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/oauthtoken" "github.com/grafana/grafana/pkg/services/oauthtoken"
"github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/util/proxyutil" "github.com/grafana/grafana/pkg/util/proxyutil"
@ -42,8 +43,9 @@ type DataSourceProxy struct {
cfg *setting.Cfg cfg *setting.Cfg
clientProvider httpclient.Provider clientProvider httpclient.Provider
oAuthTokenService oauthtoken.OAuthTokenService oAuthTokenService oauthtoken.OAuthTokenService
dataSourcesService *datasources.Service dataSourcesService datasources.DataSourceService
tracer tracing.Tracer tracer tracing.Tracer
secretsService secrets.Service
} }
type handleResponseTransport struct { type handleResponseTransport struct {
@ -78,8 +80,8 @@ func (lw *logWrapper) Write(p []byte) (n int, err error) {
// NewDataSourceProxy creates a new Datasource proxy // NewDataSourceProxy creates a new Datasource proxy
func NewDataSourceProxy(ds *models.DataSource, pluginRoutes []*plugins.Route, ctx *models.ReqContext, func NewDataSourceProxy(ds *models.DataSource, pluginRoutes []*plugins.Route, ctx *models.ReqContext,
proxyPath string, cfg *setting.Cfg, clientProvider httpclient.Provider, proxyPath string, cfg *setting.Cfg, clientProvider httpclient.Provider,
oAuthTokenService oauthtoken.OAuthTokenService, dsService *datasources.Service, oAuthTokenService oauthtoken.OAuthTokenService, dsService datasources.DataSourceService,
tracer tracing.Tracer) (*DataSourceProxy, error) { tracer tracing.Tracer, secretsService secrets.Service) (*DataSourceProxy, error) {
targetURL, err := datasource.ValidateURL(ds.Type, ds.Url) targetURL, err := datasource.ValidateURL(ds.Type, ds.Url)
if err != nil { if err != nil {
return nil, err return nil, err
@ -96,6 +98,7 @@ func NewDataSourceProxy(ds *models.DataSource, pluginRoutes []*plugins.Route, ct
oAuthTokenService: oAuthTokenService, oAuthTokenService: oAuthTokenService,
dataSourcesService: dsService, dataSourcesService: dsService,
tracer: tracer, tracer: tracer,
secretsService: secretsService,
}, nil }, nil
} }
@ -250,7 +253,7 @@ func (proxy *DataSourceProxy) director(req *http.Request) {
} }
} }
secureJsonData, err := proxy.dataSourcesService.SecretsService.DecryptJsonData(req.Context(), proxy.ds.SecureJsonData) secureJsonData, err := proxy.secretsService.DecryptJsonData(req.Context(), proxy.ds.SecureJsonData)
if err != nil { if err != nil {
logger.Error("Error interpolating proxy url", "error", err) logger.Error("Error interpolating proxy url", "error", err)
return return

@ -20,7 +20,7 @@ import (
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins"
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/datasources" datasourceservice "github.com/grafana/grafana/pkg/services/datasources/service"
"github.com/grafana/grafana/pkg/services/oauthtoken" "github.com/grafana/grafana/pkg/services/oauthtoken"
"github.com/grafana/grafana/pkg/services/secrets" "github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/services/secrets/fakes" "github.com/grafana/grafana/pkg/services/secrets/fakes"
@ -129,9 +129,9 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t.Run("When matching route path", func(t *testing.T) { t.Run("When matching route path", func(t *testing.T) {
ctx, req := setUp() ctx, req := setUp()
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "api/v4/some/method", cfg, httpClientProvider, proxy, err := NewDataSourceProxy(ds, routes, ctx, "api/v4/some/method", cfg, httpClientProvider,
&oauthtoken.Service{}, dsService, tracer) &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
proxy.matchedRoute = routes[0] proxy.matchedRoute = routes[0]
ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, proxy.matchedRoute, dsInfo, cfg) ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, proxy.matchedRoute, dsInfo, cfg)
@ -142,8 +142,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t.Run("When matching route path and has dynamic url", func(t *testing.T) { t.Run("When matching route path and has dynamic url", func(t *testing.T) {
ctx, req := setUp() ctx, req := setUp()
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "api/common/some/method", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "api/common/some/method", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
proxy.matchedRoute = routes[3] proxy.matchedRoute = routes[3]
ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, proxy.matchedRoute, dsInfo, cfg) ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, proxy.matchedRoute, dsInfo, cfg)
@ -154,8 +154,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t.Run("When matching route path with no url", func(t *testing.T) { t.Run("When matching route path with no url", func(t *testing.T) {
ctx, req := setUp() ctx, req := setUp()
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
proxy.matchedRoute = routes[4] proxy.matchedRoute = routes[4]
ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, proxy.matchedRoute, dsInfo, cfg) ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, proxy.matchedRoute, dsInfo, cfg)
@ -165,8 +165,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t.Run("When matching route path and has dynamic body", func(t *testing.T) { t.Run("When matching route path and has dynamic body", func(t *testing.T) {
ctx, req := setUp() ctx, req := setUp()
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "api/body", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "api/body", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
proxy.matchedRoute = routes[5] proxy.matchedRoute = routes[5]
ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, proxy.matchedRoute, dsInfo, cfg) ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, proxy.matchedRoute, dsInfo, cfg)
@ -179,8 +179,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t.Run("Validating request", func(t *testing.T) { t.Run("Validating request", func(t *testing.T) {
t.Run("plugin route with valid role", func(t *testing.T) { t.Run("plugin route with valid role", func(t *testing.T) {
ctx, _ := setUp() ctx, _ := setUp()
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "api/v4/some/method", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "api/v4/some/method", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
err = proxy.validateRequest() err = proxy.validateRequest()
require.NoError(t, err) require.NoError(t, err)
@ -188,8 +188,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t.Run("plugin route with admin role and user is editor", func(t *testing.T) { t.Run("plugin route with admin role and user is editor", func(t *testing.T) {
ctx, _ := setUp() ctx, _ := setUp()
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "api/admin", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "api/admin", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
err = proxy.validateRequest() err = proxy.validateRequest()
require.Error(t, err) require.Error(t, err)
@ -198,8 +198,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
t.Run("plugin route with admin role and user is admin", func(t *testing.T) { t.Run("plugin route with admin role and user is admin", func(t *testing.T) {
ctx, _ := setUp() ctx, _ := setUp()
ctx.SignedInUser.OrgRole = models.ROLE_ADMIN ctx.SignedInUser.OrgRole = models.ROLE_ADMIN
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "api/admin", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "api/admin", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
err = proxy.validateRequest() err = proxy.validateRequest()
require.NoError(t, err) require.NoError(t, err)
@ -289,8 +289,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
}, },
} }
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "pathwithtoken1", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "pathwithtoken1", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, routes[0], dsInfo, cfg) ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, routes[0], dsInfo, cfg)
@ -305,8 +305,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
req, err := http.NewRequest("GET", "http://localhost/asd", nil) req, err := http.NewRequest("GET", "http://localhost/asd", nil)
require.NoError(t, err) require.NoError(t, err)
client = newFakeHTTPClient(t, json2) client = newFakeHTTPClient(t, json2)
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "pathwithtoken2", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "pathwithtoken2", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, routes[1], dsInfo, cfg) ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, routes[1], dsInfo, cfg)
@ -322,8 +322,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
client = newFakeHTTPClient(t, []byte{}) client = newFakeHTTPClient(t, []byte{})
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "pathwithtoken1", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "pathwithtoken1", cfg, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, routes[0], dsInfo, cfg) ApplyRoute(proxy.ctx.Req.Context(), req, proxy.proxyPath, routes[0], dsInfo, cfg)
@ -344,8 +344,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
ctx := &models.ReqContext{} ctx := &models.ReqContext{}
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "/render", &setting.Cfg{BuildVersion: "5.3.0"}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "/render", &setting.Cfg{BuildVersion: "5.3.0"}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
req, err := http.NewRequest(http.MethodGet, "http://grafana.com/sub", nil) req, err := http.NewRequest(http.MethodGet, "http://grafana.com/sub", nil)
require.NoError(t, err) require.NoError(t, err)
@ -370,8 +370,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
ctx := &models.ReqContext{} ctx := &models.ReqContext{}
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
req, err := http.NewRequest(http.MethodGet, "http://grafana.com/sub", nil) req, err := http.NewRequest(http.MethodGet, "http://grafana.com/sub", nil)
@ -394,8 +394,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
ctx := &models.ReqContext{} ctx := &models.ReqContext{}
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
requestURL, err := url.Parse("http://grafana.com/sub") requestURL, err := url.Parse("http://grafana.com/sub")
@ -422,8 +422,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
ctx := &models.ReqContext{} ctx := &models.ReqContext{}
var pluginRoutes []*plugins.Route var pluginRoutes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, pluginRoutes, ctx, "", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, pluginRoutes, ctx, "", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
requestURL, err := url.Parse("http://grafana.com/sub") requestURL, err := url.Parse("http://grafana.com/sub")
@ -445,8 +445,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
ctx := &models.ReqContext{} ctx := &models.ReqContext{}
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "/path/to/folder/", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "/path/to/folder/", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
req, err := http.NewRequest(http.MethodGet, "http://grafana.com/sub", nil) req, err := http.NewRequest(http.MethodGet, "http://grafana.com/sub", nil)
req.Header.Set("Origin", "grafana.com") req.Header.Set("Origin", "grafana.com")
@ -509,8 +509,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "/path/to/folder/", &setting.Cfg{}, httpClientProvider, &mockAuthToken, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "/path/to/folder/", &setting.Cfg{}, httpClientProvider, &mockAuthToken, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
req, err = http.NewRequest(http.MethodGet, "http://grafana.com/sub", nil) req, err = http.NewRequest(http.MethodGet, "http://grafana.com/sub", nil)
require.NoError(t, err) require.NoError(t, err)
@ -642,8 +642,8 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
ctx, ds := setUp(t) ctx, ds := setUp(t)
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "/render", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "/render", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
proxy.HandleRequest() proxy.HandleRequest()
@ -660,8 +660,8 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
}) })
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "/render", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "/render", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
proxy.HandleRequest() proxy.HandleRequest()
@ -674,8 +674,8 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
ctx, ds := setUp(t) ctx, ds := setUp(t)
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "/render", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "/render", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
proxy.HandleRequest() proxy.HandleRequest()
@ -696,8 +696,8 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
}) })
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "/render", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "/render", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
proxy.HandleRequest() proxy.HandleRequest()
@ -721,8 +721,8 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
ctx.Req = httptest.NewRequest("GET", "/api/datasources/proxy/1/path/%2Ftest%2Ftest%2F?query=%2Ftest%2Ftest%2F", nil) ctx.Req = httptest.NewRequest("GET", "/api/datasources/proxy/1/path/%2Ftest%2Ftest%2F?query=%2Ftest%2Ftest%2F", nil)
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "/path/%2Ftest%2Ftest%2F", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "/path/%2Ftest%2Ftest%2F", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
proxy.HandleRequest() proxy.HandleRequest()
@ -745,8 +745,8 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
ctx.Req = httptest.NewRequest("GET", "/api/datasources/proxy/1/path/%2Ftest%2Ftest%2F?query=%2Ftest%2Ftest%2F", nil) ctx.Req = httptest.NewRequest("GET", "/api/datasources/proxy/1/path/%2Ftest%2Ftest%2F?query=%2Ftest%2Ftest%2F", nil)
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "/path/%2Ftest%2Ftest%2F", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "/path/%2Ftest%2Ftest%2F", &setting.Cfg{}, httpClientProvider, &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
proxy.HandleRequest() proxy.HandleRequest()
@ -770,8 +770,8 @@ func TestNewDataSourceProxy_InvalidURL(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
_, err = NewDataSourceProxy(&ds, routes, &ctx, "api/method", &cfg, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer) _, err = NewDataSourceProxy(&ds, routes, &ctx, "api/method", &cfg, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer, secretsService)
require.Error(t, err) require.Error(t, err)
assert.True(t, strings.HasPrefix(err.Error(), `validation of data source URL "://host/root" failed`)) assert.True(t, strings.HasPrefix(err.Error(), `validation of data source URL "://host/root" failed`))
} }
@ -791,8 +791,8 @@ func TestNewDataSourceProxy_ProtocolLessURL(t *testing.T) {
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
_, err = NewDataSourceProxy(&ds, routes, &ctx, "api/method", &cfg, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer) _, err = NewDataSourceProxy(&ds, routes, &ctx, "api/method", &cfg, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
} }
@ -834,8 +834,8 @@ func TestNewDataSourceProxy_MSSQL(t *testing.T) {
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
p, err := NewDataSourceProxy(&ds, routes, &ctx, "api/method", &cfg, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer) p, err := NewDataSourceProxy(&ds, routes, &ctx, "api/method", &cfg, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer, secretsService)
if tc.err == nil { if tc.err == nil {
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, &url.URL{ assert.Equal(t, &url.URL{
@ -861,8 +861,8 @@ func getDatasourceProxiedRequest(t *testing.T, ctx *models.ReqContext, cfg *sett
var routes []*plugins.Route var routes []*plugins.Route
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(ds, routes, ctx, "", cfg, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(ds, routes, ctx, "", cfg, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
req, err := http.NewRequest(http.MethodGet, "http://grafana.com/sub", nil) req, err := http.NewRequest(http.MethodGet, "http://grafana.com/sub", nil)
require.NoError(t, err) require.NoError(t, err)
@ -985,8 +985,8 @@ func runDatasourceAuthTest(t *testing.T, secretsService secrets.Service, test *t
require.NoError(t, err) require.NoError(t, err)
var routes []*plugins.Route var routes []*plugins.Route
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(test.datasource, routes, ctx, "", &setting.Cfg{}, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(test.datasource, routes, ctx, "", &setting.Cfg{}, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
req, err := http.NewRequest(http.MethodGet, "http://grafana.com/sub", nil) req, err := http.NewRequest(http.MethodGet, "http://grafana.com/sub", nil)
@ -1027,8 +1027,8 @@ func Test_PathCheck(t *testing.T) {
} }
ctx, _ := setUp() ctx, _ := setUp()
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
proxy, err := NewDataSourceProxy(&models.DataSource{}, routes, ctx, "b", &setting.Cfg{}, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer) proxy, err := NewDataSourceProxy(&models.DataSource{}, routes, ctx, "b", &setting.Cfg{}, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer, secretsService)
require.NoError(t, err) require.NoError(t, err)
require.Nil(t, proxy.validateRequest()) require.Nil(t, proxy.validateRequest())

@ -37,6 +37,7 @@ import (
"github.com/grafana/grafana/pkg/services/dashboardsnapshots" "github.com/grafana/grafana/pkg/services/dashboardsnapshots"
"github.com/grafana/grafana/pkg/services/datasourceproxy" "github.com/grafana/grafana/pkg/services/datasourceproxy"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
datasourceservice "github.com/grafana/grafana/pkg/services/datasources/service"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/hooks" "github.com/grafana/grafana/pkg/services/hooks"
"github.com/grafana/grafana/pkg/services/libraryelements" "github.com/grafana/grafana/pkg/services/libraryelements"
@ -183,7 +184,8 @@ var wireBasicSet = wire.NewSet(
wire.Bind(new(secrets.Store), new(*secretsDatabase.SecretsStoreImpl)), wire.Bind(new(secrets.Store), new(*secretsDatabase.SecretsStoreImpl)),
grafanads.ProvideService, grafanads.ProvideService,
dashboardsnapshots.ProvideService, dashboardsnapshots.ProvideService,
datasources.ProvideService, datasourceservice.ProvideService,
wire.Bind(new(datasources.DataSourceService), new(*datasourceservice.Service)),
pluginsettings.ProvideService, pluginsettings.ProvideService,
alerting.ProvideService, alerting.ProvideService,
serviceaccountsmanager.ProvideServiceAccountsService, serviceaccountsmanager.ProvideServiceAccountsService,

@ -18,6 +18,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions" "github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
datasourceservice "github.com/grafana/grafana/pkg/services/datasources/service"
"github.com/grafana/grafana/pkg/services/encryption" "github.com/grafana/grafana/pkg/services/encryption"
"github.com/grafana/grafana/pkg/services/encryption/ossencryption" "github.com/grafana/grafana/pkg/services/encryption/ossencryption"
"github.com/grafana/grafana/pkg/services/kmsproviders" "github.com/grafana/grafana/pkg/services/kmsproviders"
@ -51,8 +52,8 @@ var wireExtsBasicSet = wire.NewSet(
wire.Bind(new(provisioning.ProvisioningService), new(*provisioning.ProvisioningServiceImpl)), wire.Bind(new(provisioning.ProvisioningService), new(*provisioning.ProvisioningServiceImpl)),
backgroundsvcs.ProvideBackgroundServiceRegistry, backgroundsvcs.ProvideBackgroundServiceRegistry,
wire.Bind(new(registry.BackgroundServiceRegistry), new(*backgroundsvcs.BackgroundServiceRegistry)), wire.Bind(new(registry.BackgroundServiceRegistry), new(*backgroundsvcs.BackgroundServiceRegistry)),
datasources.ProvideCacheService, datasourceservice.ProvideCacheService,
wire.Bind(new(datasources.CacheService), new(*datasources.CacheServiceImpl)), wire.Bind(new(datasources.CacheService), new(*datasourceservice.CacheServiceImpl)),
migrations.ProvideOSSMigrations, migrations.ProvideOSSMigrations,
wire.Bind(new(registry.DatabaseMigrator), new(*migrations.OSSMigrations)), wire.Bind(new(registry.DatabaseMigrator), new(*migrations.OSSMigrations)),
authinfoservice.ProvideOSSUserProtectionService, authinfoservice.ProvideOSSUserProtectionService,

@ -16,13 +16,15 @@ import (
"github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/oauthtoken" "github.com/grafana/grafana/pkg/services/oauthtoken"
"github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
) )
func ProvideService(dataSourceCache datasources.CacheService, plugReqValidator models.PluginRequestValidator, func ProvideService(dataSourceCache datasources.CacheService, plugReqValidator models.PluginRequestValidator,
pluginStore plugins.Store, cfg *setting.Cfg, httpClientProvider httpclient.Provider, pluginStore plugins.Store, cfg *setting.Cfg, httpClientProvider httpclient.Provider,
oauthTokenService *oauthtoken.Service, dsService *datasources.Service, tracer tracing.Tracer) *DataSourceProxyService { oauthTokenService *oauthtoken.Service, dsService datasources.DataSourceService,
tracer tracing.Tracer, secretsService secrets.Service) *DataSourceProxyService {
return &DataSourceProxyService{ return &DataSourceProxyService{
DataSourceCache: dataSourceCache, DataSourceCache: dataSourceCache,
PluginRequestValidator: plugReqValidator, PluginRequestValidator: plugReqValidator,
@ -32,6 +34,7 @@ func ProvideService(dataSourceCache datasources.CacheService, plugReqValidator m
OAuthTokenService: oauthTokenService, OAuthTokenService: oauthTokenService,
DataSourcesService: dsService, DataSourcesService: dsService,
tracer: tracer, tracer: tracer,
secretsService: secretsService,
} }
} }
@ -42,8 +45,9 @@ type DataSourceProxyService struct {
Cfg *setting.Cfg Cfg *setting.Cfg
HTTPClientProvider httpclient.Provider HTTPClientProvider httpclient.Provider
OAuthTokenService *oauthtoken.Service OAuthTokenService *oauthtoken.Service
DataSourcesService *datasources.Service DataSourcesService datasources.DataSourceService
tracer tracing.Tracer tracer tracing.Tracer
secretsService secrets.Service
} }
func (p *DataSourceProxyService) ProxyDataSourceRequest(c *models.ReqContext) { func (p *DataSourceProxyService) ProxyDataSourceRequest(c *models.ReqContext) {
@ -87,7 +91,7 @@ func (p *DataSourceProxyService) ProxyDatasourceRequestWithID(c *models.ReqConte
proxyPath := getProxyPath(c) proxyPath := getProxyPath(c)
proxy, err := pluginproxy.NewDataSourceProxy(ds, plugin.Routes, c, proxyPath, p.Cfg, p.HTTPClientProvider, proxy, err := pluginproxy.NewDataSourceProxy(ds, plugin.Routes, c, proxyPath, p.Cfg, p.HTTPClientProvider,
p.OAuthTokenService, p.DataSourcesService, p.tracer) p.OAuthTokenService, p.DataSourcesService, p.tracer, p.secretsService)
if err != nil { if err != nil {
if errors.Is(err, datasource.URLValidationError{}) { if errors.Is(err, datasource.URLValidationError{}) {
c.JsonApiErr(http.StatusBadRequest, fmt.Sprintf("Invalid data source URL: %q", ds.Url), err) c.JsonApiErr(http.StatusBadRequest, fmt.Sprintf("Invalid data source URL: %q", ds.Url), err)

@ -0,0 +1,62 @@
package datasources
import (
"context"
"net/http"
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/models"
)
// DataSourceService interface for interacting with datasources.
type DataSourceService interface {
// GetDataSource gets a datasource.
GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error
// GetDataSources gets datasources.
GetDataSources(ctx context.Context, query *models.GetDataSourcesQuery) error
// GetDataSourcesByType gets datasources by type.
GetDataSourcesByType(ctx context.Context, query *models.GetDataSourcesByTypeQuery) error
// AddDataSource adds a new datasource.
AddDataSource(ctx context.Context, cmd *models.AddDataSourceCommand) error
// DeleteDataSource deletes an existing datasource.
DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSourceCommand) error
// UpdateDataSource updates an existing datasource.
UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSourceCommand) error
// GetDefaultDataSource gets the default datasource.
GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error
// GetHTTPTransport gets a datasource specific HTTP transport.
GetHTTPTransport(ds *models.DataSource, provider httpclient.Provider, customMiddlewares ...sdkhttpclient.Middleware) (http.RoundTripper, error)
// DecryptedValues decrypts the encrypted secureJSONData of the provided datasource and
// returns the decrypted values.
DecryptedValues(ds *models.DataSource) map[string]string
// DecryptedValue decrypts the encrypted datasource secureJSONData identified by key
// and returns the decryped value.
DecryptedValue(ds *models.DataSource, key string) (string, bool)
// DecryptedBasicAuthPassword decrypts the encrypted datasource basic authentication
// password and returns the decryped value.
DecryptedBasicAuthPassword(ds *models.DataSource) string
// DecryptedPassword decrypts the encrypted datasource password and returns the
// decryped value.
DecryptedPassword(ds *models.DataSource) string
}
// CacheService interface for retrieving a cached datasource.
type CacheService interface {
// GetDatasource gets a datasource identified by datasource numeric identifier.
GetDatasource(ctx context.Context, datasourceID int64, user *models.SignedInUser, skipCache bool) (*models.DataSource, error)
// GetDatasourceByUID gets a datasource identified by datasource unique identifier (UID).
GetDatasourceByUID(ctx context.Context, datasourceUID string, user *models.SignedInUser, skipCache bool) (*models.DataSource, error)
}

@ -1,9 +0,0 @@
package datasources
import (
"github.com/grafana/grafana/pkg/infra/log"
)
var (
plog = log.New("datasources")
)

@ -1,4 +1,4 @@
package datasources package service
import ( import (
"context" "context"
@ -6,23 +6,21 @@ import (
"time" "time"
"github.com/grafana/grafana/pkg/infra/localcache" "github.com/grafana/grafana/pkg/infra/localcache"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
) )
func ProvideCacheService(cacheService *localcache.CacheService, sqlStore *sqlstore.SQLStore) *CacheServiceImpl { func ProvideCacheService(cacheService *localcache.CacheService, sqlStore *sqlstore.SQLStore) *CacheServiceImpl {
return &CacheServiceImpl{ return &CacheServiceImpl{
logger: log.New("datasources"),
CacheService: cacheService, CacheService: cacheService,
SQLStore: sqlStore, SQLStore: sqlStore,
} }
} }
type CacheService interface {
GetDatasource(ctx context.Context, datasourceID int64, user *models.SignedInUser, skipCache bool) (*models.DataSource, error)
GetDatasourceByUID(ctx context.Context, datasourceUID string, user *models.SignedInUser, skipCache bool) (*models.DataSource, error)
}
type CacheServiceImpl struct { type CacheServiceImpl struct {
logger log.Logger
CacheService *localcache.CacheService CacheService *localcache.CacheService
SQLStore *sqlstore.SQLStore SQLStore *sqlstore.SQLStore
} }
@ -44,7 +42,7 @@ func (dc *CacheServiceImpl) GetDatasource(
} }
} }
plog.Debug("Querying for data source via SQL store", "id", datasourceID, "orgId", user.OrgId) dc.logger.Debug("Querying for data source via SQL store", "id", datasourceID, "orgId", user.OrgId)
query := &models.GetDataSourceQuery{Id: datasourceID, OrgId: user.OrgId} query := &models.GetDataSourceQuery{Id: datasourceID, OrgId: user.OrgId}
err := dc.SQLStore.GetDataSource(ctx, query) err := dc.SQLStore.GetDataSource(ctx, query)
@ -84,7 +82,7 @@ func (dc *CacheServiceImpl) GetDatasourceByUID(
} }
} }
plog.Debug("Querying for data source via SQL store", "uid", datasourceUID, "orgId", user.OrgId) dc.logger.Debug("Querying for data source via SQL store", "uid", datasourceUID, "orgId", user.OrgId)
query := &models.GetDataSourceQuery{Uid: datasourceUID, OrgId: user.OrgId} query := &models.GetDataSourceQuery{Uid: datasourceUID, OrgId: user.OrgId}
err := dc.SQLStore.GetDataSource(ctx, query) err := dc.SQLStore.GetDataSource(ctx, query)
if err != nil { if err != nil {

@ -1,4 +1,4 @@
package datasources package service
import ( import (
"context" "context"
@ -77,7 +77,9 @@ func ProvideService(bus bus.Bus, store *sqlstore.SQLStore, secretsService secret
return s return s
} }
// DataSourceRetriever interface for retrieving a datasource.
type DataSourceRetriever interface { type DataSourceRetriever interface {
// GetDataSource gets a datasource.
GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error
} }

@ -1,4 +1,4 @@
package datasources package service
import ( import (
"context" "context"

@ -21,10 +21,11 @@ var oAuthIsOAuthPassThruEnabledFunc = func(oAuthTokenService oauthtoken.OAuthTok
type Service struct { type Service struct {
pluginsClient plugins.Client pluginsClient plugins.Client
oAuthTokenService oauthtoken.OAuthTokenService oAuthTokenService oauthtoken.OAuthTokenService
dataSourcesService *datasources.Service dataSourcesService datasources.DataSourceService
} }
func ProvideService(pluginsClient plugins.Client, oAuthTokenService oauthtoken.OAuthTokenService, dataSourcesService *datasources.Service) *Service { func ProvideService(pluginsClient plugins.Client, oAuthTokenService oauthtoken.OAuthTokenService,
dataSourcesService datasources.DataSourceService) *Service {
return &Service{ return &Service{
pluginsClient: pluginsClient, pluginsClient: pluginsClient,
oAuthTokenService: oAuthTokenService, oAuthTokenService: oAuthTokenService,

@ -10,7 +10,7 @@ import (
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins"
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/datasources" datasourceservice "github.com/grafana/grafana/pkg/services/datasources/service"
"github.com/grafana/grafana/pkg/services/oauthtoken" "github.com/grafana/grafana/pkg/services/oauthtoken"
"github.com/grafana/grafana/pkg/services/secrets/fakes" "github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
@ -36,7 +36,7 @@ func TestHandleRequest(t *testing.T) {
return backend.NewQueryDataResponse(), nil return backend.NewQueryDataResponse(), nil
} }
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
dsService := datasources.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{}) dsService := datasourceservice.ProvideService(bus.New(), nil, secretsService, &acmock.Mock{})
s := ProvideService(client, nil, dsService) s := ProvideService(client, nil, dsService)
ds := &models.DataSource{Id: 12, Type: "unregisteredType", JsonData: simplejson.New()} ds := &models.DataSource{Id: 12, Type: "unregisteredType", JsonData: simplejson.New()}

Loading…
Cancel
Save