* Encryption: Add support to encrypt/decrypt sjd * Add datasources.Service as a proxy to datasources db operations * Encrypt ds.SecureJsonData before calling SQLStore * Move ds cache code into ds service * Fix tlsmanager tests * Fix pluginproxy tests * Remove some securejsondata.GetEncryptedJsonData usages * Add pluginsettings.Service as a proxy for plugin settings db operations * Add AlertNotificationService as a proxy for alert notification db operations * Remove some securejsondata.GetEncryptedJsonData usages * Remove more securejsondata.GetEncryptedJsonData usages * Fix lint errors * Minor fixes * Remove encryption global functions usages from ngalert * Fix lint errors * Minor fixes * Minor fixes * Remove securejsondata.DecryptedValue usage * Refactor the refactor * Remove securejsondata.DecryptedValue usage * Move securejsondata to migrations package * Move securejsondata to migrations package * Minor fix * Fix integration test * Fix integration tests * Undo undesired changes * Fix tests * Add context.Context into encryption methods * Fix tests * Fix tests * Fix tests * Trigger CI * Fix test * Add names to params of encryption service interface * Remove bus from CacheServiceImpl * Add logging * Add keys to logger Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com> * Add missing key to logger Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com> * Undo changes in markdown files * Fix formatting * Add context to secrets service * Rename decryptSecureJsonData to decryptSecureJsonDataFn * Name args in GetDecryptedValueFn * Add template back to NewAlertmanagerNotifier * Copy GetDecryptedValueFn to ngalert * Add logging to pluginsettings * Fix pluginsettings test Co-authored-by: Tania B <yalyna.ts@gmail.com> Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com>
163 lines
5.3 KiB
Go
163 lines
5.3 KiB
Go
package tsdb
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
"github.com/grafana/grafana/pkg/bus"
|
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
|
"github.com/grafana/grafana/pkg/models"
|
|
"github.com/grafana/grafana/pkg/plugins"
|
|
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
|
"github.com/grafana/grafana/pkg/plugins/manager"
|
|
"github.com/grafana/grafana/pkg/services/datasources"
|
|
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
"github.com/stretchr/testify/require"
|
|
"golang.org/x/oauth2"
|
|
)
|
|
|
|
func TestHandleRequest(t *testing.T) {
|
|
t.Run("Should return query result when handling request for query", func(t *testing.T) {
|
|
req := plugins.DataQuery{
|
|
Queries: []plugins.DataSubQuery{
|
|
{RefID: "A", DataSource: &models.DataSource{Id: 1, Type: "test"}},
|
|
},
|
|
}
|
|
|
|
svc, exe, _ := createService()
|
|
exe.Return("A", plugins.DataTimeSeriesSlice{plugins.DataTimeSeries{Name: "argh"}})
|
|
|
|
res, err := svc.HandleRequest(context.TODO(), &models.DataSource{Id: 1, Type: "test"}, req)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, res.Results["A"].Series)
|
|
require.Equal(t, "argh", res.Results["A"].Series[0].Name)
|
|
})
|
|
|
|
t.Run("Should return query results when handling request for two queries with same data source", func(t *testing.T) {
|
|
req := plugins.DataQuery{
|
|
Queries: []plugins.DataSubQuery{
|
|
{RefID: "A", DataSource: &models.DataSource{Id: 1, Type: "test"}},
|
|
{RefID: "B", DataSource: &models.DataSource{Id: 1, Type: "test"}},
|
|
},
|
|
}
|
|
|
|
svc, exe, _ := createService()
|
|
exe.Return("A", plugins.DataTimeSeriesSlice{plugins.DataTimeSeries{Name: "argh"}})
|
|
exe.Return("B", plugins.DataTimeSeriesSlice{plugins.DataTimeSeries{Name: "barg"}})
|
|
|
|
res, err := svc.HandleRequest(context.TODO(), &models.DataSource{Id: 1, Type: "test"}, req)
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, res.Results, 2)
|
|
require.Equal(t, "argh", res.Results["A"].Series[0].Name)
|
|
require.Equal(t, "barg", res.Results["B"].Series[0].Name)
|
|
})
|
|
|
|
t.Run("Should fallback to backend plugin manager when handling request for query with unregistered type", func(t *testing.T) {
|
|
svc, _, manager := createService()
|
|
backendPluginManagerCalled := false
|
|
manager.QueryDataHandlerFunc = backend.QueryDataHandlerFunc(func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
|
backendPluginManagerCalled = true
|
|
return &backend.QueryDataResponse{}, nil
|
|
})
|
|
|
|
ds := &models.DataSource{Id: 12, Type: "unregisteredType", JsonData: simplejson.New()}
|
|
req := plugins.DataQuery{
|
|
TimeRange: &plugins.DataTimeRange{},
|
|
Queries: []plugins.DataSubQuery{
|
|
{
|
|
RefID: "A",
|
|
DataSource: ds,
|
|
Model: simplejson.New(),
|
|
},
|
|
},
|
|
}
|
|
_, err := svc.HandleRequest(context.Background(), ds, req)
|
|
require.NoError(t, err)
|
|
require.True(t, backendPluginManagerCalled)
|
|
})
|
|
}
|
|
|
|
//nolint: staticcheck // plugins.DataPlugin deprecated
|
|
type resultsFn func(context plugins.DataQuery) plugins.DataQueryResult
|
|
|
|
type fakeExecutor struct {
|
|
//nolint: staticcheck // plugins.DataPlugin deprecated
|
|
results map[string]plugins.DataQueryResult
|
|
resultsFn map[string]resultsFn
|
|
}
|
|
|
|
//nolint: staticcheck // plugins.DataPlugin deprecated
|
|
func (e *fakeExecutor) DataQuery(ctx context.Context, dsInfo *models.DataSource, context plugins.DataQuery) (
|
|
plugins.DataResponse, error) {
|
|
result := plugins.DataResponse{Results: make(map[string]plugins.DataQueryResult)}
|
|
for _, query := range context.Queries {
|
|
if results, has := e.results[query.RefID]; has {
|
|
result.Results[query.RefID] = results
|
|
}
|
|
if testFunc, has := e.resultsFn[query.RefID]; has {
|
|
result.Results[query.RefID] = testFunc(context)
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (e *fakeExecutor) Return(refID string, series plugins.DataTimeSeriesSlice) {
|
|
//nolint: staticcheck // plugins.DataPlugin deprecated
|
|
e.results[refID] = plugins.DataQueryResult{
|
|
RefID: refID, Series: series,
|
|
}
|
|
}
|
|
|
|
func (e *fakeExecutor) HandleQuery(refId string, fn resultsFn) {
|
|
e.resultsFn[refId] = fn
|
|
}
|
|
|
|
type fakeBackendPM struct {
|
|
backendplugin.Manager
|
|
backend.QueryDataHandlerFunc
|
|
}
|
|
|
|
func (m *fakeBackendPM) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
|
if m.QueryDataHandlerFunc != nil {
|
|
return m.QueryDataHandlerFunc.QueryData(ctx, req)
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
type fakeOAuthTokenService struct {
|
|
}
|
|
|
|
func (s *fakeOAuthTokenService) GetCurrentOAuthToken(context.Context, *models.SignedInUser) *oauth2.Token {
|
|
return nil
|
|
}
|
|
|
|
func (s *fakeOAuthTokenService) IsOAuthPassThruEnabled(*models.DataSource) bool {
|
|
return false
|
|
}
|
|
|
|
func createService() (*Service, *fakeExecutor, *fakeBackendPM) {
|
|
fakeBackendPM := &fakeBackendPM{}
|
|
manager := &manager.PluginManager{
|
|
BackendPluginManager: fakeBackendPM,
|
|
}
|
|
dsService := datasources.ProvideService(bus.New(), nil, ossencryption.ProvideService())
|
|
|
|
s := newService(setting.NewCfg(), manager, fakeBackendPM, &fakeOAuthTokenService{}, dsService)
|
|
e := &fakeExecutor{
|
|
//nolint: staticcheck // plugins.DataPlugin deprecated
|
|
results: make(map[string]plugins.DataQueryResult),
|
|
resultsFn: make(map[string]resultsFn),
|
|
}
|
|
//nolint: staticcheck // plugins.DataPlugin deprecated
|
|
s.registry["test"] = func(*models.DataSource) (plugins.DataPlugin, error) {
|
|
return e, nil
|
|
}
|
|
|
|
return s, e, fakeBackendPM
|
|
}
|