diff --git a/data/converters/converters.go b/data/converters/converters.go index 2ba967423..bb0bd6e3a 100644 --- a/data/converters/converters.go +++ b/data/converters/converters.go @@ -2,6 +2,7 @@ package converters import ( + "encoding/json" "fmt" "strconv" "time" @@ -229,6 +230,10 @@ var JSONValueToFloat64 = data.FieldConverter{ fV = float64(iiV) return fV, nil } + nn, ok := v.(json.Number) + if ok { + return nn.Float64() + } sV, ok := v.(string) if ok { return strconv.ParseFloat(sV, 64) @@ -254,6 +259,14 @@ var JSONValueToInt64 = data.FieldConverter{ if ok { return int64(fV), nil } + ii, ok := v.(int) + if ok { + return int64(ii), nil + } + nn, ok := v.(json.Number) + if ok { + return nn.Int64() + } return nil, toConversionError("float64", v) }, } diff --git a/experimental/apis/data/v0alpha1/client.go b/experimental/apis/data/v0alpha1/client.go index b84ae196a..37e01249d 100644 --- a/experimental/apis/data/v0alpha1/client.go +++ b/experimental/apis/data/v0alpha1/client.go @@ -46,16 +46,18 @@ func (c *simpleHTTPClient) QueryData(ctx context.Context, query QueryDataRequest } req.Header.Set("Content-Type", "application/json") - rsp, err := c.client.Do(req) - if err != nil { - return rsp.StatusCode, nil, err - } - defer rsp.Body.Close() - qdr := &backend.QueryDataResponse{} - iter, err := jsoniter.Parse(jsoniter.ConfigCompatibleWithStandardLibrary, rsp.Body, 1024*10) - if err == nil { - err = iter.ReadVal(qdr) + code := http.StatusNotFound // 404 for network requests etc + rsp, err := c.client.Do(req) + if rsp != nil { + code = rsp.StatusCode + defer rsp.Body.Close() + if err == nil { + iter, e2 := jsoniter.Parse(jsoniter.ConfigCompatibleWithStandardLibrary, rsp.Body, 1024*10) + if e2 == nil { + err = iter.ReadVal(qdr) + } + } } - return rsp.StatusCode, qdr, err + return code, qdr, err } diff --git a/experimental/apis/data/v0alpha1/client_test.go b/experimental/apis/data/v0alpha1/client_test.go index b7915b0dd..d604e1a47 100644 --- a/experimental/apis/data/v0alpha1/client_test.go +++ b/experimental/apis/data/v0alpha1/client_test.go @@ -11,6 +11,13 @@ import ( "github.com/stretchr/testify/require" ) +func TestClientWithBadURL(t *testing.T) { + client := v0alpha1.NewQueryDataClient("http://localhostXYZ:998/api/ds/query", nil, nil) + code, _, err := client.QueryData(context.Background(), v0alpha1.QueryDataRequest{}) + require.Error(t, err) + require.Equal(t, 404, code) +} + func TestQueryClient(t *testing.T) { t.Skip() @@ -30,7 +37,7 @@ func TestQueryClient(t *testing.T) { "uid": "PD8C576611E62080A" }, "csvContent": "a,b,c\n1,hello,true", - "hide": true + "hide": false } ] }` diff --git a/experimental/apis/data/v0alpha1/query.go b/experimental/apis/data/v0alpha1/query.go index a382f0ded..f079d0ed4 100644 --- a/experimental/apis/data/v0alpha1/query.go +++ b/experimental/apis/data/v0alpha1/query.go @@ -5,6 +5,7 @@ import ( "fmt" "unsafe" + "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/data" "github.com/grafana/grafana-plugin-sdk-go/data/converters" "github.com/grafana/grafana-plugin-sdk-go/data/utils/jsoniter" @@ -51,35 +52,59 @@ func (g *DataQuery) Set(key string, val any) *DataQuery { case "refId": g.RefID, _ = val.(string) case "resultAssertions": + v, ok := val.(ResultAssertions) + if ok { + g.ResultAssertions = &v + return g + } body, err := json.Marshal(val) - if err != nil { - _ = json.Unmarshal(body, &g.ResultAssertions) + if err == nil { + err = json.Unmarshal(body, &g.ResultAssertions) + if err != nil { + backend.Logger.Warn("error reading resultAssertions from value. %w", err) + } } case "timeRange": + v, ok := val.(TimeRange) + if ok { + g.TimeRange = &v + return g + } body, err := json.Marshal(val) - if err != nil { - _ = json.Unmarshal(body, &g.TimeRange) + if err == nil { + err = json.Unmarshal(body, &g.TimeRange) + if err != nil { + backend.Logger.Warn("error reading timeRange from value. %w", err) + } } case "datasource": + v, ok := val.(DataSourceRef) + if ok { + g.Datasource = &v + return g + } body, err := json.Marshal(val) - if err != nil { - _ = json.Unmarshal(body, &g.Datasource) + if err == nil { + err = json.Unmarshal(body, &g.Datasource) + if err != nil { + backend.Logger.Warn("error reading datasource from value. %w", err) + } } case "datasourceId": v, err := converters.JSONValueToInt64.Converter(val) - if err != nil { + if err == nil { g.DatasourceID, _ = v.(int64) } case "queryType": g.QueryType, _ = val.(string) case "maxDataPoints": v, err := converters.JSONValueToInt64.Converter(val) - if err != nil { + if err == nil { g.MaxDataPoints, _ = v.(int64) } case "intervalMs": v, err := converters.JSONValueToFloat64.Converter(val) - if err != nil { + if err == nil { g.IntervalMS, _ = v.(float64) } case "hide": diff --git a/experimental/apis/data/v0alpha1/query_test.go b/experimental/apis/data/v0alpha1/query_test.go index 51ba48ab9..fd1efd714 100644 --- a/experimental/apis/data/v0alpha1/query_test.go +++ b/experimental/apis/data/v0alpha1/query_test.go @@ -115,4 +115,15 @@ func TestQueryBuilders(t *testing.T) { }) require.Equal(t, "D", testQ3.QueryType) require.Equal(t, "E", testQ3.GetString("extra")) + + testQ3.Set("datasource", &DataSourceRef{Type: "TYPE", UID: "UID"}) + require.NotNil(t, testQ3.Datasource) + require.Equal(t, "TYPE", testQ3.Datasource.Type) + require.Equal(t, "UID", testQ3.Datasource.UID) + + testQ3.Set("datasource", map[string]any{"uid": "XYZ"}) + require.Equal(t, "XYZ", testQ3.Datasource.UID) + + testQ3.Set("maxDataPoints", 100) + require.Equal(t, int64(100), testQ3.MaxDataPoints) }