Query Service: Fix Time Bug (#108337)

pull/108344/head
Sarah Zinger 2 days ago committed by GitHub
parent 7626508842
commit f34127c449
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 7
      pkg/expr/nodes.go
  2. 20
      pkg/services/mtdsclient/mt_datasource_client_builder.go
  3. 7
      pkg/services/query/query.go
  4. 142
      pkg/services/query/query_test.go

@ -408,7 +408,12 @@ func (dn *DSNode) Execute(ctx context.Context, now time.Time, _ mathexp.Vars, s
}
} else {
// transform request from backend.QueryDataRequest to k8s request
k8sReq := &data.QueryDataRequest{}
k8sReq := &data.QueryDataRequest{
TimeRange: data.TimeRange{
From: req.Queries[0].TimeRange.From.Format(time.RFC3339),
To: req.Queries[0].TimeRange.To.Format(time.RFC3339),
},
}
for _, q := range req.Queries {
var dataQuery data.DataQuery
err := json.Unmarshal(q.JSON, &dataQuery)

@ -64,3 +64,23 @@ func NewMtDatasourceClientBuilderWithClientSupplier(
logger: logger,
}
}
func NewTestMTDSClientBuilder(isMultiTenant bool, mockClient clientapi.QueryDataClient) MTDatasourceClientBuilder {
return &testBuilder{
mockClient: mockClient,
isMultitenant: isMultiTenant,
}
}
type testBuilder struct {
mockClient clientapi.QueryDataClient
isMultitenant bool
}
func (b *testBuilder) BuildClient(pluginId string, uid string) (clientapi.QueryDataClient, bool) {
if !b.isMultitenant {
return nil, false
}
return b.mockClient, true
}

@ -295,7 +295,12 @@ func (s *ServiceImpl) handleQuerySingleDatasource(ctx context.Context, user iden
return s.pluginClient.QueryData(ctx, req)
} else { // multi tenant flow
// transform request from backend.QueryDataRequest to k8s request
k8sReq := &data.QueryDataRequest{}
k8sReq := &data.QueryDataRequest{
TimeRange: data.TimeRange{
From: req.Queries[0].TimeRange.From.Format(time.RFC3339),
To: req.Queries[0].TimeRange.To.Format(time.RFC3339),
},
}
for _, q := range req.Queries {
var dataQuery data.DataQuery
err := json.Unmarshal(q.JSON, &dataQuery)

@ -12,6 +12,7 @@ import (
"time"
"github.com/grafana/grafana-plugin-sdk-go/backend"
data "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -24,6 +25,7 @@ import (
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/registry/apis/query/clientapi"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
@ -50,7 +52,7 @@ func TestMain(m *testing.M) {
func TestIntegrationParseMetricRequest(t *testing.T) {
t.Run("Test a simple single datasource query", func(t *testing.T) {
tc := setup(t)
tc := setup(t, false, nil)
mr := metricRequestWithQueries(t, `{
"refId": "A",
"datasource": {
@ -74,7 +76,7 @@ func TestIntegrationParseMetricRequest(t *testing.T) {
})
t.Run("Test a single datasource query with expressions", func(t *testing.T) {
tc := setup(t)
tc := setup(t, false, nil)
mr := metricRequestWithQueries(t, `{
"refId": "A",
"datasource": {
@ -114,7 +116,7 @@ func TestIntegrationParseMetricRequest(t *testing.T) {
})
t.Run("Test a simple mixed datasource query", func(t *testing.T) {
tc := setup(t)
tc := setup(t, false, nil)
mr := metricRequestWithQueries(t, `{
"refId": "A",
"datasource": {
@ -147,7 +149,7 @@ func TestIntegrationParseMetricRequest(t *testing.T) {
})
t.Run("Test a mixed datasource query with expressions", func(t *testing.T) {
tc := setup(t)
tc := setup(t, false, nil)
mr := metricRequestWithQueries(t, `{
"refId": "A",
"datasource": {
@ -208,7 +210,7 @@ func TestIntegrationParseMetricRequest(t *testing.T) {
})
t.Run("Header validation", func(t *testing.T) {
tc := setup(t)
tc := setup(t, false, nil)
mr := metricRequestWithQueries(t, `{
"refId": "A",
"datasource": {
@ -250,7 +252,7 @@ func TestIntegrationParseMetricRequest(t *testing.T) {
})
t.Run("Test a duplicated refId", func(t *testing.T) {
tc := setup(t)
tc := setup(t, false, nil)
mr := metricRequestWithQueries(t, `{
"refId": "A",
"datasource": {
@ -271,7 +273,7 @@ func TestIntegrationParseMetricRequest(t *testing.T) {
func TestIntegrationQueryDataMultipleSources(t *testing.T) {
t.Run("can query multiple datasources", func(t *testing.T) {
tc := setup(t)
tc := setup(t, false, nil)
query1, err := simplejson.NewJson([]byte(`
{
"datasource": {
@ -320,7 +322,7 @@ func TestIntegrationQueryDataMultipleSources(t *testing.T) {
})
t.Run("can query multiple datasources with an expression present", func(t *testing.T) {
tc := setup(t)
tc := setup(t, false, nil)
query1, err := simplejson.NewJson([]byte(`
{
"datasource": {
@ -386,7 +388,7 @@ func TestIntegrationQueryDataMultipleSources(t *testing.T) {
})
t.Run("error is returned in query when one of the queries fails", func(t *testing.T) {
tc := setup(t)
tc := setup(t, false, nil)
query1, _ := simplejson.NewJson([]byte(`
{
@ -426,7 +428,7 @@ func TestIntegrationQueryDataMultipleSources(t *testing.T) {
})
t.Run("ignores a deprecated datasourceID", func(t *testing.T) {
tc := setup(t)
tc := setup(t, false, nil)
query1, err := simplejson.NewJson([]byte(`
{
"datasource": {
@ -452,7 +454,63 @@ func TestIntegrationQueryDataMultipleSources(t *testing.T) {
})
}
func setup(t *testing.T) *testContext {
func TestIntegrationQueryDataWithMTDSClient(t *testing.T) {
t.Run("can run a simple datasource query with a mt ds client", func(t *testing.T) {
stubbedResponse := &backend.QueryDataResponse{Responses: make(backend.Responses)}
testClient := &testClient{
queryDataStubbedResponse: stubbedResponse,
}
tc := setup(t, true, testClient)
mr := metricRequestWithQueries(t, `{
"refId": "A",
"datasource": {
"uid": "gIEkMvIVz",
"type": "postgres"
}
}`, `{
"refId": "B",
"datasource": {
"uid": "gIEkMvIVz",
"type": "postgres"
}
}`)
mr.From = "2022-01-01"
mr.To = "2022-01-02"
ctx := context.Background()
_, err := tc.queryService.QueryData(ctx, tc.signedInUser, true, mr)
require.NoError(t, err)
assert.Equal(t, data.QueryDataRequest{
TimeRange: data.TimeRange{
From: "2022-01-01T00:00:00Z",
To: "2022-01-02T00:00:00Z",
},
Queries: []data.DataQuery{
{
CommonQueryProperties: data.CommonQueryProperties{
RefID: "A",
Datasource: &data.DataSourceRef{
Type: "postgres",
UID: "gIEkMvIVz",
},
},
},
{
CommonQueryProperties: data.CommonQueryProperties{
RefID: "B",
Datasource: &data.DataSourceRef{
Type: "postgres",
UID: "gIEkMvIVz",
},
},
},
},
Debug: false,
}, testClient.queryDataLastCalledWith)
})
}
func setup(t *testing.T, isMultiTenant bool, mockClient clientapi.QueryDataClient) *testContext {
dss := []*datasources.DataSource{
{UID: "gIEkMvIVz", Type: "postgres"},
{UID: "sEx6ZvSVk", Type: "testdata"},
@ -468,24 +526,55 @@ func setup(t *testing.T) *testContext {
sqlStore, cfg := db.InitTestDBWithCfg(t)
secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore())
ss := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger"))
fakeDatasourceService := &fakeDatasources.FakeDataSourceService{
DataSources: dss,
SimulatePluginFailure: false,
}
pCtxProvider := plugincontext.ProvideService(cfg,
localcache.ProvideService(), &pluginstore.FakePluginStore{
pCtxProvider := plugincontext.ProvideService(
cfg,
localcache.ProvideService(),
&pluginstore.FakePluginStore{
PluginList: []pluginstore.Plugin{
{JSONData: plugins.JSONData{ID: "postgres"}},
{JSONData: plugins.JSONData{ID: "testdata"}},
{JSONData: plugins.JSONData{ID: "mysql"}},
},
}, &fakeDatasources.FakeCacheService{}, fakeDatasourceService,
pluginSettings.ProvideService(sqlStore, secretsService), pluginconfig.NewFakePluginRequestConfigProvider(),
},
&fakeDatasources.FakeCacheService{},
fakeDatasourceService,
pluginSettings.ProvideService(sqlStore, secretsService),
pluginconfig.NewFakePluginRequestConfigProvider(),
)
var mtdsClientBuilder mtdsclient.MTDatasourceClientBuilder
if isMultiTenant {
mtdsClientBuilder = mtdsclient.NewTestMTDSClientBuilder(isMultiTenant, mockClient)
} else {
mtdsClientBuilder = mtdsclient.NewTestMTDSClientBuilder(false, nil)
}
exprService := expr.ProvideService(
&setting.Cfg{ExpressionsEnabled: true},
pc,
pCtxProvider,
featuremgmt.WithFeatures(),
nil,
tracing.InitializeTracerForTest(),
mtdsClientBuilder,
)
exprService := expr.ProvideService(&setting.Cfg{ExpressionsEnabled: true}, pc, pCtxProvider,
featuremgmt.WithFeatures(), nil, tracing.InitializeTracerForTest(), mtdsclient.NewNullMTDatasourceClientBuilder())
queryService := ProvideService(setting.NewCfg(), dc, exprService, rv, pc, pCtxProvider, mtdsclient.NewNullMTDatasourceClientBuilder()) // provider belonging to this package
queryService := ProvideService(
setting.NewCfg(),
dc,
exprService,
rv,
pc,
pCtxProvider,
mtdsClientBuilder,
)
return &testContext{
pluginContext: pc,
secretStore: ss,
@ -573,3 +662,20 @@ func (c *fakePluginClient) QueryData(ctx context.Context, req *backend.QueryData
return &backend.QueryDataResponse{Responses: make(backend.Responses)}, nil
}
type testClient struct {
queryDataLastCalledWith data.QueryDataRequest
queryDataStubbedResponse *backend.QueryDataResponse
queryDataStubbedError error
}
func (c *testClient) QueryData(ctx context.Context, req data.QueryDataRequest) (*backend.QueryDataResponse, error) {
c.queryDataLastCalledWith = req
if c.queryDataStubbedError != nil {
return nil, c.queryDataStubbedError
}
if c.queryDataStubbedResponse != nil {
return c.queryDataStubbedResponse, nil
}
return nil, errors.New("no response stubbed")
}

Loading…
Cancel
Save