diff --git a/pkg/tsdb/influxdb/healthcheck.go b/pkg/tsdb/influxdb/healthcheck.go index ecf6d358a3b..aefde0e70cc 100644 --- a/pkg/tsdb/influxdb/healthcheck.go +++ b/pkg/tsdb/influxdb/healthcheck.go @@ -11,6 +11,7 @@ import ( "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/tsdb/influxdb/flux" "github.com/grafana/grafana/pkg/tsdb/influxdb/fsql" + "github.com/grafana/grafana/pkg/tsdb/influxdb/influxql" "github.com/grafana/grafana/pkg/tsdb/influxdb/models" ) @@ -34,7 +35,7 @@ func (s *Service) CheckHealth(ctx context.Context, req *backend.CheckHealthReque case influxVersionFlux: return CheckFluxHealth(ctx, dsInfo, req) case influxVersionInfluxQL: - return CheckInfluxQLHealth(ctx, dsInfo, s) + return CheckInfluxQLHealth(ctx, dsInfo) case influxVersionSQL: return CheckSQLHealth(ctx, dsInfo, req) default: @@ -77,30 +78,22 @@ func CheckFluxHealth(ctx context.Context, dsInfo *models.DatasourceInfo, return getHealthCheckMessage(logger, "", errors.New("error getting flux query buckets")) } -func CheckInfluxQLHealth(ctx context.Context, dsInfo *models.DatasourceInfo, s *Service) (*backend.CheckHealthResult, error) { +func CheckInfluxQLHealth(ctx context.Context, dsInfo *models.DatasourceInfo) (*backend.CheckHealthResult, error) { logger := logger.FromContext(ctx) - queryString := "SHOW measurements" - hcRequest, err := s.createRequest(ctx, logger, dsInfo, queryString) - if err != nil { - return getHealthCheckMessage(logger, "error creating influxDB healthcheck request", err) - } - res, err := dsInfo.HTTPClient.Do(hcRequest) + resp, err := influxql.Query(ctx, dsInfo, &backend.QueryDataRequest{ + Queries: []backend.DataQuery{ + { + RefID: refID, + QueryType: "health", + JSON: []byte(`{"query": "SHOW measurements", "rawQuery": true}`), + }, + }, + }) if err != nil { return getHealthCheckMessage(logger, "error performing influxQL query", err) } - defer func() { - if err := res.Body.Close(); err != nil { - logger.Warn("failed to close response body", "err", err) - } - }() - - resp := s.responseParser.Parse(res.Body, res.StatusCode, []Query{{ - RefID: refID, - UseRawQuery: true, - RawQuery: queryString, - }}) if res, ok := resp.Responses[refID]; ok { if res.Error != nil { return getHealthCheckMessage(logger, "error reading influxDB", res.Error) diff --git a/pkg/tsdb/influxdb/influxdb.go b/pkg/tsdb/influxdb/influxdb.go index 22065be250c..be4a030d971 100644 --- a/pkg/tsdb/influxdb/influxdb.go +++ b/pkg/tsdb/influxdb/influxdb.go @@ -3,12 +3,7 @@ package influxdb import ( "context" "encoding/json" - "errors" "fmt" - "net/http" - "net/url" - "path" - "strings" "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend/datasource" @@ -19,26 +14,19 @@ import ( "github.com/grafana/grafana/pkg/infra/httpclient" "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/tsdb/influxdb/influxql" "github.com/grafana/grafana/pkg/tsdb/influxdb/models" ) var logger log.Logger = log.New("tsdb.influxdb") type Service struct { - queryParser *InfluxdbQueryParser - responseParser *ResponseParser - im instancemgmt.InstanceManager } -var ErrInvalidHttpMode = errors.New("'httpMode' should be either 'GET' or 'POST'") - func ProvideService(httpClient httpclient.Provider) *Service { return &Service{ - queryParser: &InfluxdbQueryParser{}, - responseParser: &ResponseParser{}, - im: datasource.NewInstanceManager(newInstanceSettings(httpClient)), + im: datasource.NewInstanceManager(newInstanceSettings(httpClient)), } } @@ -106,102 +94,19 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) if err != nil { return nil, err } - version := dsInfo.Version - if version == influxVersionFlux { + + logger.Debug(fmt.Sprintf("Making a %s type query", dsInfo.Version)) + + switch dsInfo.Version { + case influxVersionFlux: return flux.Query(ctx, dsInfo, *req) - } - if version == influxVersionSQL { + case influxVersionInfluxQL: + return influxql.Query(ctx, dsInfo, req) + case influxVersionSQL: return fsql.Query(ctx, dsInfo, *req) - } - - logger.Debug("Making a non-Flux type query") - - var allRawQueries string - queries := make([]Query, 0, len(req.Queries)) - - for _, reqQuery := range req.Queries { - query, err := s.queryParser.Parse(reqQuery) - if err != nil { - return &backend.QueryDataResponse{}, err - } - - rawQuery, err := query.Build(req) - if err != nil { - return &backend.QueryDataResponse{}, err - } - - allRawQueries = allRawQueries + rawQuery + ";" - query.RefID = reqQuery.RefID - query.RawQuery = rawQuery - queries = append(queries, *query) - } - - if setting.Env == setting.Dev { - logger.Debug("Influxdb query", "raw query", allRawQueries) - } - - request, err := s.createRequest(ctx, logger, dsInfo, allRawQueries) - if err != nil { - return &backend.QueryDataResponse{}, err - } - - res, err := dsInfo.HTTPClient.Do(request) - if err != nil { - return &backend.QueryDataResponse{}, err - } - defer func() { - if err := res.Body.Close(); err != nil { - logger.Warn("Failed to close response body", "err", err) - } - }() - - resp := s.responseParser.Parse(res.Body, res.StatusCode, queries) - - return resp, nil -} - -func (s *Service) createRequest(ctx context.Context, logger log.Logger, dsInfo *models.DatasourceInfo, query string) (*http.Request, error) { - u, err := url.Parse(dsInfo.URL) - if err != nil { - return nil, err - } - - u.Path = path.Join(u.Path, "query") - httpMode := dsInfo.HTTPMode - - var req *http.Request - switch httpMode { - case "GET": - req, err = http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) - if err != nil { - return nil, err - } - case "POST": - bodyValues := url.Values{} - bodyValues.Add("q", query) - body := bodyValues.Encode() - req, err = http.NewRequestWithContext(ctx, http.MethodPost, u.String(), strings.NewReader(body)) - if err != nil { - return nil, err - } default: - return nil, ErrInvalidHttpMode + return nil, fmt.Errorf("unknown influxdb version") } - - params := req.URL.Query() - params.Set("db", dsInfo.DbName) - params.Set("epoch", "ms") - - if httpMode == "GET" { - params.Set("q", query) - } else if httpMode == "POST" { - req.Header.Set("Content-type", "application/x-www-form-urlencoded") - } - - req.URL.RawQuery = params.Encode() - - logger.Debug("Influxdb request", "url", req.URL.String()) - return req, nil } func (s *Service) getDSInfo(ctx context.Context, pluginCtx backend.PluginContext) (*models.DatasourceInfo, error) { diff --git a/pkg/tsdb/influxdb/influxql/influxql.go b/pkg/tsdb/influxdb/influxql/influxql.go new file mode 100644 index 00000000000..d84144aa415 --- /dev/null +++ b/pkg/tsdb/influxdb/influxql/influxql.go @@ -0,0 +1,125 @@ +package influxql + +import ( + "context" + "errors" + "net/http" + "net/url" + "path" + "strings" + + "github.com/grafana/grafana-plugin-sdk-go/backend" + + "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/tsdb/influxdb/models" +) + +const defaultRetentionPolicy = "default" + +var ( + ErrInvalidHttpMode = errors.New("'httpMode' should be either 'GET' or 'POST'") + glog = log.New("tsdb.influx_influxql") +) + +func Query(ctx context.Context, dsInfo *models.DatasourceInfo, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { + logger := glog.FromContext(ctx) + response := backend.NewQueryDataResponse() + + for _, reqQuery := range req.Queries { + query, err := models.QueryParse(reqQuery) + if err != nil { + return &backend.QueryDataResponse{}, err + } + + rawQuery, err := query.Build(req) + if err != nil { + return &backend.QueryDataResponse{}, err + } + + query.RefID = reqQuery.RefID + query.RawQuery = rawQuery + + if setting.Env == setting.Dev { + logger.Debug("Influxdb query", "raw query", rawQuery) + } + + request, err := createRequest(ctx, logger, dsInfo, rawQuery, query.Policy) + if err != nil { + return &backend.QueryDataResponse{}, err + } + + resp, err := execute(dsInfo, logger, query, request) + + if err != nil { + response.Responses[query.RefID] = backend.DataResponse{Error: err} + } else { + response.Responses[query.RefID] = resp + } + } + + return response, nil +} + +func createRequest(ctx context.Context, logger log.Logger, dsInfo *models.DatasourceInfo, queryStr string, retentionPolicy string) (*http.Request, error) { + u, err := url.Parse(dsInfo.URL) + if err != nil { + return nil, err + } + + u.Path = path.Join(u.Path, "query") + httpMode := dsInfo.HTTPMode + + var req *http.Request + switch httpMode { + case "GET": + req, err = http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) + if err != nil { + return nil, err + } + case "POST": + bodyValues := url.Values{} + bodyValues.Add("q", queryStr) + body := bodyValues.Encode() + req, err = http.NewRequestWithContext(ctx, http.MethodPost, u.String(), strings.NewReader(body)) + if err != nil { + return nil, err + } + default: + return nil, ErrInvalidHttpMode + } + + params := req.URL.Query() + params.Set("db", dsInfo.DbName) + params.Set("epoch", "ms") + // default is hardcoded default retention policy + // InfluxDB will use the default policy when it is not added to the request + if retentionPolicy != "" && retentionPolicy != "default" { + params.Set("rp", retentionPolicy) + } + + if httpMode == "GET" { + params.Set("q", queryStr) + } else if httpMode == "POST" { + req.Header.Set("Content-type", "application/x-www-form-urlencoded") + } + + req.URL.RawQuery = params.Encode() + + logger.Debug("Influxdb request", "url", req.URL.String()) + return req, nil +} + +func execute(dsInfo *models.DatasourceInfo, logger log.Logger, query *models.Query, request *http.Request) (backend.DataResponse, error) { + res, err := dsInfo.HTTPClient.Do(request) + if err != nil { + return backend.DataResponse{}, err + } + defer func() { + if err := res.Body.Close(); err != nil { + logger.Warn("Failed to close response body", "err", err) + } + }() + resp := ResponseParse(res.Body, res.StatusCode, query) + return *resp, nil +} diff --git a/pkg/tsdb/influxdb/influxdb_test.go b/pkg/tsdb/influxdb/influxql/influxql_test.go similarity index 74% rename from pkg/tsdb/influxdb/influxdb_test.go rename to pkg/tsdb/influxdb/influxql/influxql_test.go index 5580e71e671..fee920f1056 100644 --- a/pkg/tsdb/influxdb/influxdb_test.go +++ b/pkg/tsdb/influxdb/influxql/influxql_test.go @@ -1,4 +1,4 @@ -package influxdb +package influxql import ( "context" @@ -9,23 +9,21 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/tsdb/influxdb/models" ) func TestExecutor_createRequest(t *testing.T) { + logger := log.New("tsdb.influx_influxql_test") datasource := &models.DatasourceInfo{ URL: "http://awesome-influxdb:1337", DbName: "awesome-db", HTTPMode: "GET", } query := "SELECT awesomeness FROM somewhere" - s := &Service{ - queryParser: &InfluxdbQueryParser{}, - responseParser: &ResponseParser{}, - } t.Run("createRequest with GET httpMode", func(t *testing.T) { - req, err := s.createRequest(context.Background(), logger, datasource, query) + req, err := createRequest(context.Background(), logger, datasource, query, defaultRetentionPolicy) require.NoError(t, err) @@ -39,7 +37,7 @@ func TestExecutor_createRequest(t *testing.T) { t.Run("createRequest with POST httpMode", func(t *testing.T) { datasource.HTTPMode = "POST" - req, err := s.createRequest(context.Background(), logger, datasource, query) + req, err := createRequest(context.Background(), logger, datasource, query, defaultRetentionPolicy) require.NoError(t, err) assert.Equal(t, "POST", req.Method) @@ -58,7 +56,7 @@ func TestExecutor_createRequest(t *testing.T) { t.Run("createRequest with PUT httpMode", func(t *testing.T) { datasource.HTTPMode = "PUT" - _, err := s.createRequest(context.Background(), logger, datasource, query) + _, err := createRequest(context.Background(), logger, datasource, query, defaultRetentionPolicy) require.EqualError(t, err, ErrInvalidHttpMode.Error()) }) } diff --git a/pkg/tsdb/influxdb/response_parser.go b/pkg/tsdb/influxdb/influxql/response_parser.go similarity index 83% rename from pkg/tsdb/influxdb/response_parser.go rename to pkg/tsdb/influxdb/influxql/response_parser.go index 3af82a51c85..314e40b9636 100644 --- a/pkg/tsdb/influxdb/response_parser.go +++ b/pkg/tsdb/influxdb/influxql/response_parser.go @@ -1,4 +1,4 @@ -package influxdb +package influxql import ( "encoding/json" @@ -11,51 +11,45 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/data" -) -type ResponseParser struct{} + "github.com/grafana/grafana/pkg/tsdb/influxdb/models" +) var ( legendFormat = regexp.MustCompile(`\[\[([\@\/\w-]+)(\.[\@\/\w-]+)*\]\]*|\$([\@\w-]+?)*`) ) -func (rp *ResponseParser) Parse(buf io.ReadCloser, statusCode int, queries []Query) *backend.QueryDataResponse { - return rp.parse(buf, statusCode, queries) +func ResponseParse(buf io.ReadCloser, statusCode int, query *models.Query) *backend.DataResponse { + return parse(buf, statusCode, query) } // parse is the same as Parse, but without the io.ReadCloser (we don't need to // close the buffer) -func (*ResponseParser) parse(buf io.Reader, statusCode int, queries []Query) *backend.QueryDataResponse { - resp := backend.NewQueryDataResponse() +func parse(buf io.Reader, statusCode int, query *models.Query) *backend.DataResponse { response, jsonErr := parseJSON(buf) if statusCode/100 != 2 { - resp.Responses["A"] = backend.DataResponse{Error: fmt.Errorf("InfluxDB returned error: %s", response.Error)} + return &backend.DataResponse{Error: fmt.Errorf("InfluxDB returned error: %s", response.Error)} } if jsonErr != nil { - resp.Responses["A"] = backend.DataResponse{Error: jsonErr} - return resp + return &backend.DataResponse{Error: jsonErr} } if response.Error != "" { - resp.Responses["A"] = backend.DataResponse{Error: fmt.Errorf(response.Error)} - return resp + return &backend.DataResponse{Error: fmt.Errorf(response.Error)} } - for i, result := range response.Results { - if result.Error != "" { - resp.Responses[queries[i].RefID] = backend.DataResponse{Error: fmt.Errorf(result.Error)} - } else { - resp.Responses[queries[i].RefID] = backend.DataResponse{Frames: transformRows(result.Series, queries[i])} - } + result := response.Results[0] + if result.Error != "" { + return &backend.DataResponse{Error: fmt.Errorf(result.Error)} + } else { + return &backend.DataResponse{Frames: transformRows(result.Series, *query)} } - - return resp } -func parseJSON(buf io.Reader) (Response, error) { - var response Response +func parseJSON(buf io.Reader) (models.Response, error) { + var response models.Response dec := json.NewDecoder(buf) dec.UseNumber() @@ -65,7 +59,7 @@ func parseJSON(buf io.Reader) (Response, error) { return response, err } -func transformRows(rows []Row, query Query) data.Frames { +func transformRows(rows []models.Row, query models.Query) data.Frames { // pre-allocate frames - this can save many allocations cols := 0 for _, row := range rows { @@ -106,7 +100,7 @@ func transformRows(rows []Row, query Query) data.Frames { return frames } -func newFrameWithTimeField(row Row, column string, colIndex int, query Query, frameName []byte) *data.Frame { +func newFrameWithTimeField(row models.Row, column string, colIndex int, query models.Query, frameName []byte) *data.Frame { var timeArray []time.Time var floatArray []*float64 var stringArray []*string @@ -164,7 +158,7 @@ func newFrameWithTimeField(row Row, column string, colIndex int, query Query, fr return newDataFrame(name, query.RawQuery, timeField, valueField) } -func newFrameWithoutTimeField(row Row, retentionPolicyQuery bool, tagValuesQuery bool) *data.Frame { +func newFrameWithoutTimeField(row models.Row, retentionPolicyQuery bool, tagValuesQuery bool) *data.Frame { var values []string if retentionPolicyQuery { @@ -213,7 +207,7 @@ func newDataFrame(name string, queryString string, timeField *data.Field, valueF return frame } -func formatFrameName(row Row, column string, query Query, frameName []byte) []byte { +func formatFrameName(row models.Row, column string, query models.Query, frameName []byte) []byte { if query.Alias == "" { return buildFrameNameFromQuery(row, column, frameName) } @@ -253,7 +247,7 @@ func formatFrameName(row Row, column string, query Query, frameName []byte) []by return result } -func buildFrameNameFromQuery(row Row, column string, frameName []byte) []byte { +func buildFrameNameFromQuery(row models.Row, column string, frameName []byte) []byte { frameName = append(frameName, row.Name...) frameName = append(frameName, '.') frameName = append(frameName, column...) @@ -329,10 +323,10 @@ func parseNumber(value interface{}) *float64 { return &fvalue } -func isTagValuesQuery(query Query) bool { +func isTagValuesQuery(query models.Query) bool { return strings.Contains(strings.ToLower(query.RawQuery), strings.ToLower("SHOW TAG VALUES")) } -func isRetentionPolicyQuery(query Query) bool { +func isRetentionPolicyQuery(query models.Query) bool { return strings.Contains(strings.ToLower(query.RawQuery), strings.ToLower("SHOW RETENTION POLICIES")) } diff --git a/pkg/tsdb/influxdb/response_parser_bench_test.go b/pkg/tsdb/influxdb/influxql/response_parser_bench_test.go similarity index 63% rename from pkg/tsdb/influxdb/response_parser_bench_test.go rename to pkg/tsdb/influxdb/influxql/response_parser_bench_test.go index 69f043f9c2e..9652ae4933c 100644 --- a/pkg/tsdb/influxdb/response_parser_bench_test.go +++ b/pkg/tsdb/influxdb/influxql/response_parser_bench_test.go @@ -1,4 +1,4 @@ -package influxdb +package influxql import ( _ "embed" @@ -6,24 +6,24 @@ import ( "testing" "github.com/stretchr/testify/require" + + "github.com/grafana/grafana/pkg/tsdb/influxdb/models" ) //go:embed testdata/response.json var testResponse string -// go test -benchmem -run=^$ -memprofile memprofile.out -count=10 -bench ^BenchmarkParseJson$ github.com/grafana/grafana/pkg/tsdb/influxdb +// go test -benchmem -run=^$ -memprofile memprofile.out -count=10 -bench ^BenchmarkParseJson$ github.com/grafana/grafana/pkg/tsdb/influxdb/influxql // go tool pprof -http=localhost:9999 memprofile.out func BenchmarkParseJson(b *testing.B) { - parser := &ResponseParser{} - query := &Query{} - queries := addQueryToQueries(*query) + query := generateQuery(models.Query{}) b.ResetTimer() for n := 0; n < b.N; n++ { buf := strings.NewReader(testResponse) - result := parser.parse(buf, 200, queries) - require.NotNil(b, result.Responses["A"].Frames) - require.NoError(b, result.Responses["A"].Error) + result := parse(buf, 200, query) + require.NotNil(b, result.Frames) + require.NoError(b, result.Error) } } diff --git a/pkg/tsdb/influxdb/response_parser_test.go b/pkg/tsdb/influxdb/influxql/response_parser_test.go similarity index 63% rename from pkg/tsdb/influxdb/response_parser_test.go rename to pkg/tsdb/influxdb/influxql/response_parser_test.go index c7fbabcc519..a47b9fb36ea 100644 --- a/pkg/tsdb/influxdb/response_parser_test.go +++ b/pkg/tsdb/influxdb/influxql/response_parser_test.go @@ -1,4 +1,4 @@ -package influxdb +package influxql import ( "encoding/json" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/tsdb/influxdb/models" "github.com/grafana/grafana/pkg/util" ) @@ -20,31 +21,29 @@ func prepare(text string) io.ReadCloser { return io.NopCloser(strings.NewReader(text)) } -func addQueryToQueries(query Query) []Query { - var queries []Query - query.RefID = "A" - query.RawQuery = "Test raw query" - queries = append(queries, query) - return queries +func generateQuery(query models.Query) *models.Query { + if query.RefID == "" { + query.RefID = "A" + } + if query.RawQuery == "" { + query.RawQuery = "Test raw query" + } + return &query } func TestInfluxdbResponseParser(t *testing.T) { t.Run("Influxdb response parser should handle invalid JSON", func(t *testing.T) { - parser := &ResponseParser{} - response := `{ invalid }` - query := &Query{} + query := models.Query{} - result := parser.Parse(prepare(response), 200, addQueryToQueries(*query)) + result := ResponseParse(prepare(response), 200, generateQuery(query)) - require.Nil(t, result.Responses["A"].Frames) - require.Error(t, result.Responses["A"].Error) + require.Nil(t, result.Frames) + require.Error(t, result.Error) }) t.Run("Influxdb response parser should parse everything normally including nil bools and nil strings", func(t *testing.T) { - parser := &ResponseParser{} - response := ` { "results": [ @@ -66,7 +65,7 @@ func TestInfluxdbResponseParser(t *testing.T) { } ` - query := &Query{} + query := models.Query{} labels, err := data.LabelsFromString("datacenter=America") require.Nil(t, err) @@ -118,23 +117,20 @@ func TestInfluxdbResponseParser(t *testing.T) { ) boolFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"} - result := parser.Parse(prepare(response), 200, addQueryToQueries(*query)) + result := ResponseParse(prepare(response), 200, generateQuery(query)) - frame := result.Responses["A"] - if diff := cmp.Diff(floatFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(floatFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - if diff := cmp.Diff(stringFrame, frame.Frames[1], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(stringFrame, result.Frames[1], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - if diff := cmp.Diff(boolFrame, frame.Frames[2], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(boolFrame, result.Frames[2], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } }) t.Run("Influxdb response parser should parse metricFindQueries normally", func(t *testing.T) { - parser := &ResponseParser{} - response := ` { "results": [ @@ -155,8 +151,7 @@ func TestInfluxdbResponseParser(t *testing.T) { } ` - var queries []Query - queries = append(queries, Query{RefID: "metricFindQuery"}) + query := models.Query{RefID: "metricFindQuery"} newField := data.NewField("Value", nil, []string{ "cpu", "disk", "logs", }) @@ -164,17 +159,14 @@ func TestInfluxdbResponseParser(t *testing.T) { newField, ) - result := parser.Parse(prepare(response), 200, queries) + result := ResponseParse(prepare(response), 200, generateQuery(query)) - frame := result.Responses["metricFindQuery"] - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } }) t.Run("Influxdb response parser should parse metricFindQueries->SHOW TAG VALUES normally", func(t *testing.T) { - parser := &ResponseParser{} - response := ` { "results": [ @@ -194,8 +186,7 @@ func TestInfluxdbResponseParser(t *testing.T) { } ` - var queries []Query - queries = append(queries, Query{RawQuery: "SHOW TAG VALUES", RefID: "metricFindQuery"}) + query := models.Query{RawQuery: "SHOW TAG VALUES", RefID: "metricFindQuery"} newField := data.NewField("Value", nil, []string{ "cpu-total", "cpu0", "cpu1", }) @@ -203,46 +194,14 @@ func TestInfluxdbResponseParser(t *testing.T) { newField, ) - result := parser.Parse(prepare(response), 200, queries) + result := ResponseParse(prepare(response), 200, generateQuery(query)) - frame := result.Responses["metricFindQuery"] - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } }) - t.Run("Influxdb response parser should parse two responses with different refIDs", func(t *testing.T) { - parser := &ResponseParser{} - - response := ` - { - "results": [ - { - "series": [{}] - }, - { - "series": [{}] - } - ] - } - ` - - query := &Query{} - var queries = addQueryToQueries(*query) - queryB := &Query{} - queryB.RefID = "B" - queries = append(queries, *queryB) - result := parser.Parse(prepare(response), 200, queries) - - assert.Len(t, result.Responses, 2) - assert.Contains(t, result.Responses, "A") - assert.Contains(t, result.Responses, "B") - assert.NotContains(t, result.Responses, "C") - }) - t.Run("Influxdb response parser populates the RawQuery in the response meta ExecutedQueryString", func(t *testing.T) { - parser := &ResponseParser{} - response := ` { "results": [ @@ -263,17 +222,14 @@ func TestInfluxdbResponseParser(t *testing.T) { } ` - query := &Query{} + query := models.Query{} query.RawQuery = "Test raw query" - result := parser.Parse(prepare(response), 200, addQueryToQueries(*query)) + result := ResponseParse(prepare(response), 200, generateQuery(query)) - frame := result.Responses["A"] - assert.Equal(t, frame.Frames[0].Meta.ExecutedQueryString, "Test raw query") + assert.Equal(t, result.Frames[0].Meta.ExecutedQueryString, "Test raw query") }) t.Run("Influxdb response parser with invalid value-format", func(t *testing.T) { - parser := &ResponseParser{} - response := ` { "results": [ @@ -294,7 +250,7 @@ func TestInfluxdbResponseParser(t *testing.T) { } ` - query := &Query{} + query := models.Query{} newField := data.NewField("Value", nil, []*float64{ util.Pointer(50.0), nil, util.Pointer(52.0), @@ -311,17 +267,14 @@ func TestInfluxdbResponseParser(t *testing.T) { ) testFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"} - result := parser.Parse(prepare(response), 200, addQueryToQueries(*query)) + result := ResponseParse(prepare(response), 200, generateQuery(query)) - frame := result.Responses["A"] - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } }) t.Run("Influxdb response parser with invalid timestamp-format", func(t *testing.T) { - parser := &ResponseParser{} - response := ` { "results": [ @@ -343,7 +296,7 @@ func TestInfluxdbResponseParser(t *testing.T) { } ` - query := &Query{} + query := models.Query{} newField := data.NewField("Value", nil, []*float64{ util.Pointer(50.0), util.Pointer(52.0), @@ -359,17 +312,14 @@ func TestInfluxdbResponseParser(t *testing.T) { ) testFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"} - result := parser.Parse(prepare(response), 200, addQueryToQueries(*query)) + result := ResponseParse(prepare(response), 200, generateQuery(query)) - frame := result.Responses["A"] - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } }) t.Run("Influxdb response parser with alias", func(t *testing.T) { - parser := &ResponseParser{} - response := ` { "results": [ @@ -395,7 +345,7 @@ func TestInfluxdbResponseParser(t *testing.T) { } ` - query := &Query{Alias: "series alias"} + query := models.Query{Alias: "series alias"} labels, err := data.LabelsFromString("/cluster/name/=Cluster/, @cluster@name@=Cluster@, cluster-name=Cluster, datacenter=America, dc.region.name=Northeast") require.Nil(t, err) newField := data.NewField("Value", labels, []*float64{ @@ -410,31 +360,28 @@ func TestInfluxdbResponseParser(t *testing.T) { newField, ) testFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"} - result := parser.Parse(prepare(response), 200, addQueryToQueries(*query)) + result := ResponseParse(prepare(response), 200, generateQuery(query)) t.Run("should parse aliases", func(t *testing.T) { - frame := result.Responses["A"] - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias $m $measurement", Measurement: "10m"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) + query = models.Query{Alias: "alias $m $measurement", Measurement: "10m"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) - frame = result.Responses["A"] name := "alias 10m 10m" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias $col", Measurement: "10m"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias $col", Measurement: "10m"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias mean" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } name = "alias sum" @@ -444,13 +391,12 @@ func TestInfluxdbResponseParser(t *testing.T) { }) testFrame.Fields[1] = newField testFrame.Fields[1].Config = &data.FieldConfig{DisplayNameFromDS: name} - if diff := cmp.Diff(testFrame, frame.Frames[1], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[1], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias $tag_datacenter"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias $tag_datacenter"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias America" testFrame.Name = name newField = data.NewField("Value", labels, []*float64{ @@ -458,13 +404,12 @@ func TestInfluxdbResponseParser(t *testing.T) { }) testFrame.Fields[1] = newField testFrame.Fields[1].Config = &data.FieldConfig{DisplayNameFromDS: name} - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias $tag_datacenter/$tag_datacenter"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias $tag_datacenter/$tag_datacenter"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias America/America" testFrame.Name = name newField = data.NewField("Value", labels, []*float64{ @@ -472,183 +417,152 @@ func TestInfluxdbResponseParser(t *testing.T) { }) testFrame.Fields[1] = newField testFrame.Fields[1].Config = &data.FieldConfig{DisplayNameFromDS: name} - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias [[col]]", Measurement: "10m"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias [[col]]", Measurement: "10m"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias mean" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias $0 $1 $2 $3 $4"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias $0 $1 $2 $3 $4"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias cpu upc $2 $3 $4" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias $0, $1 - $2 - $3, $4: something"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias $0, $1 - $2 - $3, $4: something"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias cpu, upc - $2 - $3, $4: something" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias $1"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias $1"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias upc" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias $5"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias $5"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias $5" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "series alias"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "series alias"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "series alias" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias [[m]] [[measurement]]", Measurement: "10m"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias [[m]] [[measurement]]", Measurement: "10m"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias 10m 10m" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias [[tag_datacenter]]"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias [[tag_datacenter]]"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias America" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias [[tag_dc.region.name]]"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias [[tag_dc.region.name]]"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias Northeast" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias [[tag_cluster-name]]"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias [[tag_cluster-name]]"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias Cluster" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias [[tag_/cluster/name/]]"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias [[tag_/cluster/name/]]"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias Cluster/" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias [[tag_@cluster@name@]]"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias [[tag_@cluster@name@]]"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias Cluster@" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } }) t.Run("shouldn't parse aliases", func(t *testing.T) { - query = &Query{Alias: "alias words with no brackets"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame := result.Responses["A"] + query = models.Query{Alias: "alias words with no brackets"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name := "alias words with no brackets" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias Test 1.5"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias Test 1.5"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias Test 1.5" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } - query = &Query{Alias: "alias Test -1"} - result = parser.Parse(prepare(response), 200, addQueryToQueries(*query)) - frame = result.Responses["A"] + query = models.Query{Alias: "alias Test -1"} + result = ResponseParse(prepare(response), 200, generateQuery(query)) name = "alias Test -1" testFrame.Name = name testFrame.Fields[1].Config.DisplayNameFromDS = name - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(testFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } }) }) t.Run("Influxdb response parser with errors", func(t *testing.T) { - parser := &ResponseParser{} - response := ` { "results": [ - { - "series": [ - { - "name": "cpu", - "columns": ["time","mean","sum"], - "tags": {"datacenter": "America"}, - "values": [ - [111,222,333], - [111,222,333], - [111,null,333] - ] - } - ] - }, { "error": "query-timeout limit exceeded" } @@ -656,11 +570,7 @@ func TestInfluxdbResponseParser(t *testing.T) { } ` - query := &Query{} - var queries = addQueryToQueries(*query) - queryB := &Query{} - queryB.RefID = "B" - queries = append(queries, *queryB) + query := models.Query{} labels, err := data.LabelsFromString("datacenter=America") require.Nil(t, err) newField := data.NewField("Value", labels, []*float64{ @@ -677,32 +587,25 @@ func TestInfluxdbResponseParser(t *testing.T) { newField, ) testFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"} - result := parser.Parse(prepare(response), 200, queries) + result := ResponseParse(prepare(response), 200, generateQuery(query)) - frame := result.Responses["A"] - if diff := cmp.Diff(testFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { - t.Errorf("Result mismatch (-want +got):\n%s", diff) - } - - require.EqualError(t, result.Responses["B"].Error, "query-timeout limit exceeded") + require.EqualError(t, result.Error, "query-timeout limit exceeded") }) t.Run("Influxdb response parser with top-level error", func(t *testing.T) { - parser := &ResponseParser{} - response := ` { "error": "error parsing query: found THING" } ` - query := &Query{} + query := models.Query{} - result := parser.Parse(prepare(response), 200, addQueryToQueries(*query)) + result := ResponseParse(prepare(response), 200, generateQuery(query)) - require.Nil(t, result.Responses["A"].Frames) + require.Nil(t, result.Frames) - require.EqualError(t, result.Responses["A"].Error, "error parsing query: found THING") + require.EqualError(t, result.Error, "error parsing query: found THING") }) t.Run("Influxdb response parser parseNumber nil", func(t *testing.T) { @@ -736,8 +639,6 @@ func TestInfluxdbResponseParser(t *testing.T) { func TestResponseParser_Parse_RetentionPolicy(t *testing.T) { t.Run("Influxdb response parser should parse metricFindQueries->SHOW RETENTION POLICIES normally", func(t *testing.T) { - parser := &ResponseParser{} - response := ` { "results": [ @@ -789,18 +690,16 @@ func TestResponseParser_Parse_RetentionPolicy(t *testing.T) { } ` - var queries []Query - queries = append(queries, Query{RefID: "metricFindQuery", RawQuery: "SHOW RETENTION POLICIES"}) + query := models.Query{RefID: "metricFindQuery", RawQuery: "SHOW RETENTION POLICIES"} policyFrame := data.NewFrame("", data.NewField("Value", nil, []string{ "bar", "autogen", "5m_avg", "1m_avg", }), ) - result := parser.Parse(prepare(response), 200, queries) + result := ResponseParse(prepare(response), 200, generateQuery(query)) - frame := result.Responses["metricFindQuery"] - if diff := cmp.Diff(policyFrame, frame.Frames[0], data.FrameTestCompareOptions()...); diff != "" { + if diff := cmp.Diff(policyFrame, result.Frames[0], data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } }) @@ -810,7 +709,7 @@ func TestResponseParser_Parse(t *testing.T) { tests := []struct { name string input string - f func(t *testing.T, got *backend.QueryDataResponse) + f func(t *testing.T, got backend.DataResponse) }{ { name: "Influxdb response parser with valid value when null values returned", @@ -823,7 +722,7 @@ func TestResponseParser_Parse(t *testing.T) { [102,52] ] }]}]}`, - f: func(t *testing.T, got *backend.QueryDataResponse) { + f: func(t *testing.T, got backend.DataResponse) { newField := data.NewField("Value", nil, []*float64{nil, nil, util.Pointer(52.0)}) newField.Config = &data.FieldConfig{DisplayNameFromDS: "cpu.mean"} testFrame := data.NewFrame("cpu.mean", @@ -836,7 +735,7 @@ func TestResponseParser_Parse(t *testing.T) { newField, ) testFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"} - assert.Equal(t, testFrame, got.Responses["A"].Frames[0]) + assert.Equal(t, testFrame, got.Frames[0]) }, }, { @@ -850,7 +749,7 @@ func TestResponseParser_Parse(t *testing.T) { [102,null] ] }]}]}`, - f: func(t *testing.T, got *backend.QueryDataResponse) { + f: func(t *testing.T, got backend.DataResponse) { newField := data.NewField("Value", nil, []*float64{nil, nil, nil}) newField.Config = &data.FieldConfig{DisplayNameFromDS: "cpu.mean"} testFrame := data.NewFrame("cpu.mean", @@ -863,17 +762,16 @@ func TestResponseParser_Parse(t *testing.T) { newField, ) testFrame.Meta = &data.FrameMeta{ExecutedQueryString: "Test raw query"} - assert.Equal(t, testFrame, got.Responses["A"].Frames[0]) + assert.Equal(t, testFrame, got.Frames[0]) }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - parser := &ResponseParser{} - got := parser.Parse(prepare(tt.input), 200, addQueryToQueries(Query{})) + got := ResponseParse(prepare(tt.input), 200, generateQuery(models.Query{})) require.NotNil(t, got) if tt.f != nil { - tt.f(t, got) + tt.f(t, *got) } }) } diff --git a/pkg/tsdb/influxdb/testdata/response.json b/pkg/tsdb/influxdb/influxql/testdata/response.json similarity index 100% rename from pkg/tsdb/influxdb/testdata/response.json rename to pkg/tsdb/influxdb/influxql/testdata/response.json diff --git a/pkg/tsdb/influxdb/mocks_test.go b/pkg/tsdb/influxdb/mocks_test.go index 091a21fffd6..4dc690c4ccb 100644 --- a/pkg/tsdb/influxdb/mocks_test.go +++ b/pkg/tsdb/influxdb/mocks_test.go @@ -113,8 +113,6 @@ func (rt *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { func GetMockService(version string, rt RoundTripper) *Service { return &Service{ - queryParser: &InfluxdbQueryParser{}, - responseParser: &ResponseParser{}, im: &fakeInstance{ version: version, fakeRoundTripper: rt, diff --git a/pkg/tsdb/influxdb/model_parser.go b/pkg/tsdb/influxdb/models/model_parser.go similarity index 83% rename from pkg/tsdb/influxdb/model_parser.go rename to pkg/tsdb/influxdb/models/model_parser.go index d33e2aec34c..4396c504a3b 100644 --- a/pkg/tsdb/influxdb/model_parser.go +++ b/pkg/tsdb/influxdb/models/model_parser.go @@ -1,4 +1,4 @@ -package influxdb +package models import ( "fmt" @@ -12,7 +12,7 @@ import ( type InfluxdbQueryParser struct{} -func (qp *InfluxdbQueryParser) Parse(query backend.DataQuery) (*Query, error) { +func QueryParse(query backend.DataQuery) (*Query, error) { model, err := simplejson.NewJson(query.JSON) if err != nil { return nil, fmt.Errorf("couldn't unmarshal query") @@ -29,17 +29,17 @@ func (qp *InfluxdbQueryParser) Parse(query backend.DataQuery) (*Query, error) { measurement := model.Get("measurement").MustString("") - tags, err := qp.parseTags(model) + tags, err := parseTags(model) if err != nil { return nil, err } - groupBys, err := qp.parseGroupBy(model) + groupBys, err := parseGroupBy(model) if err != nil { return nil, err } - selects, err := qp.parseSelects(model) + selects, err := parseSelects(model) if err != nil { return nil, err } @@ -70,7 +70,7 @@ func (qp *InfluxdbQueryParser) Parse(query backend.DataQuery) (*Query, error) { }, nil } -func (qp *InfluxdbQueryParser) parseSelects(model *simplejson.Json) ([]*Select, error) { +func parseSelects(model *simplejson.Json) ([]*Select, error) { selectObjs := model.Get("select").MustArray() result := make([]*Select, 0, len(selectObjs)) @@ -80,7 +80,7 @@ func (qp *InfluxdbQueryParser) parseSelects(model *simplejson.Json) ([]*Select, for _, partObj := range selectJson.MustArray() { part := simplejson.NewFromAny(partObj) - queryPart, err := qp.parseQueryPart(part) + queryPart, err := parseQueryPart(part) if err != nil { return nil, err } @@ -94,7 +94,7 @@ func (qp *InfluxdbQueryParser) parseSelects(model *simplejson.Json) ([]*Select, return result, nil } -func (*InfluxdbQueryParser) parseTags(model *simplejson.Json) ([]*Tag, error) { +func parseTags(model *simplejson.Json) ([]*Tag, error) { tags := model.Get("tags").MustArray() result := make([]*Tag, 0, len(tags)) for _, t := range tags { @@ -128,7 +128,7 @@ func (*InfluxdbQueryParser) parseTags(model *simplejson.Json) ([]*Tag, error) { return result, nil } -func (*InfluxdbQueryParser) parseQueryPart(model *simplejson.Json) (*QueryPart, error) { +func parseQueryPart(model *simplejson.Json) (*QueryPart, error) { typ, err := model.Get("type").String() if err != nil { return nil, err @@ -161,12 +161,12 @@ func (*InfluxdbQueryParser) parseQueryPart(model *simplejson.Json) (*QueryPart, return qp, nil } -func (qp *InfluxdbQueryParser) parseGroupBy(model *simplejson.Json) ([]*QueryPart, error) { +func parseGroupBy(model *simplejson.Json) ([]*QueryPart, error) { groupBy := model.Get("groupBy").MustArray() result := make([]*QueryPart, 0, len(groupBy)) for _, groupObj := range groupBy { groupJson := simplejson.NewFromAny(groupObj) - queryPart, err := qp.parseQueryPart(groupJson) + queryPart, err := parseQueryPart(groupJson) if err != nil { return nil, err } diff --git a/pkg/tsdb/influxdb/model_parser_test.go b/pkg/tsdb/influxdb/models/model_parser_test.go similarity index 96% rename from pkg/tsdb/influxdb/model_parser_test.go rename to pkg/tsdb/influxdb/models/model_parser_test.go index d6ad0775357..2396b110015 100644 --- a/pkg/tsdb/influxdb/model_parser_test.go +++ b/pkg/tsdb/influxdb/models/model_parser_test.go @@ -1,4 +1,4 @@ -package influxdb +package models import ( "testing" @@ -9,8 +9,6 @@ import ( ) func TestInfluxdbQueryParser_Parse(t *testing.T) { - parser := &InfluxdbQueryParser{} - t.Run("can parse influxdb json model", func(t *testing.T) { json := ` { @@ -110,7 +108,7 @@ func TestInfluxdbQueryParser_Parse(t *testing.T) { Interval: time.Second * 20, } - res, err := parser.Parse(query) + res, err := QueryParse(query) require.NoError(t, err) require.Len(t, res.GroupBy, 3) require.Len(t, res.Selects, 3) @@ -173,7 +171,7 @@ func TestInfluxdbQueryParser_Parse(t *testing.T) { Interval: time.Second * 10, } - res, err := parser.Parse(query) + res, err := QueryParse(query) require.NoError(t, err) require.Equal(t, "RawDummyQuery", res.RawQuery) require.Len(t, res.GroupBy, 2) @@ -196,7 +194,7 @@ func TestInfluxdbQueryParser_Parse(t *testing.T) { Interval: time.Millisecond * 0, } - res, err := parser.Parse(query) + res, err := QueryParse(query) require.NoError(t, err) require.Equal(t, time.Millisecond*1, res.Interval) }) diff --git a/pkg/tsdb/influxdb/models.go b/pkg/tsdb/influxdb/models/models.go similarity index 98% rename from pkg/tsdb/influxdb/models.go rename to pkg/tsdb/influxdb/models/models.go index 56fd4246f71..f9544d1d610 100644 --- a/pkg/tsdb/influxdb/models.go +++ b/pkg/tsdb/influxdb/models/models.go @@ -1,4 +1,4 @@ -package influxdb +package models import "time" diff --git a/pkg/tsdb/influxdb/query.go b/pkg/tsdb/influxdb/models/query.go similarity index 99% rename from pkg/tsdb/influxdb/query.go rename to pkg/tsdb/influxdb/models/query.go index 2c62b898ade..0c6155521b4 100644 --- a/pkg/tsdb/influxdb/query.go +++ b/pkg/tsdb/influxdb/models/query.go @@ -1,4 +1,4 @@ -package influxdb +package models import ( "fmt" diff --git a/pkg/tsdb/influxdb/query_part.go b/pkg/tsdb/influxdb/models/query_part.go similarity index 99% rename from pkg/tsdb/influxdb/query_part.go rename to pkg/tsdb/influxdb/models/query_part.go index eba7b8a5553..4391762533c 100644 --- a/pkg/tsdb/influxdb/query_part.go +++ b/pkg/tsdb/influxdb/models/query_part.go @@ -1,4 +1,4 @@ -package influxdb +package models import ( "fmt" diff --git a/pkg/tsdb/influxdb/query_part_test.go b/pkg/tsdb/influxdb/models/query_part_test.go similarity index 99% rename from pkg/tsdb/influxdb/query_part_test.go rename to pkg/tsdb/influxdb/models/query_part_test.go index 0204c14ca46..e39589db8fb 100644 --- a/pkg/tsdb/influxdb/query_part_test.go +++ b/pkg/tsdb/influxdb/models/query_part_test.go @@ -1,4 +1,4 @@ -package influxdb +package models import ( "testing" diff --git a/pkg/tsdb/influxdb/query_test.go b/pkg/tsdb/influxdb/models/query_test.go similarity index 99% rename from pkg/tsdb/influxdb/query_test.go rename to pkg/tsdb/influxdb/models/query_test.go index e767748bff4..8bda0359394 100644 --- a/pkg/tsdb/influxdb/query_test.go +++ b/pkg/tsdb/influxdb/models/query_test.go @@ -1,4 +1,4 @@ -package influxdb +package models import ( "strings"