diff --git a/pkg/models/dashboard_queries.go b/pkg/models/dashboard_queries.go index f0b470acb19..5f3338f00a2 100644 --- a/pkg/models/dashboard_queries.go +++ b/pkg/models/dashboard_queries.go @@ -10,7 +10,7 @@ func GetUniqueDashboardDatasourceUids(dashboard *simplejson.Json) []string { for _, panelObj := range dashboard.Get("panels").MustArray() { panel := simplejson.NewFromAny(panelObj) - uid := panel.Get("datasource").Get("uid").MustString() + uid := GetDataSourceUidFromJson(panel) // if uid is for a mixed datasource, get the datasource uids from the targets if uid == "-- Mixed --" { @@ -44,8 +44,11 @@ func GroupQueriesByPanelId(dashboard *simplejson.Json) map[int64][]*simplejson.J for _, queryObj := range panel.Get("targets").MustArray() { query := simplejson.NewFromAny(queryObj) + // if query target has no datasource, set it to have the datasource on the panel if _, ok := query.CheckGet("datasource"); !ok { - query.Set("datasource", panel.Get("datasource")) + uid := GetDataSourceUidFromJson(panel) + datasource := map[string]interface{}{"type": "public-ds", "uid": uid} + query.Set("datasource", datasource) } panelQueries = append(panelQueries, query) @@ -61,13 +64,8 @@ func GroupQueriesByDataSource(queries []*simplejson.Json) (result [][]*simplejso byDataSource := make(map[string][]*simplejson.Json) for _, query := range queries { - dataSourceUid, err := query.GetPath("datasource", "uid").String() - - if err != nil { - continue - } - - byDataSource[dataSourceUid] = append(byDataSource[dataSourceUid], query) + uid := GetDataSourceUidFromJson(query) + byDataSource[uid] = append(byDataSource[uid], query) } for _, queries := range byDataSource { @@ -76,3 +74,14 @@ func GroupQueriesByDataSource(queries []*simplejson.Json) (result [][]*simplejso return } + +func GetDataSourceUidFromJson(query *simplejson.Json) string { + uid := query.Get("datasource").Get("uid").MustString() + + // before 8.3 special types could be sent as datasource (expr) + if uid == "" { + uid = query.Get("datasource").MustString() + } + + return uid +} diff --git a/pkg/models/dashboard_queries_test.go b/pkg/models/dashboard_queries_test.go index afa160515ab..553c58a6c37 100644 --- a/pkg/models/dashboard_queries_test.go +++ b/pkg/models/dashboard_queries_test.go @@ -20,6 +20,37 @@ const ( "schemaVersion": 35 }` + dashboardWithTargetsWithNoDatasources = ` +{ + "panels": [ + { + "id": 2, + "datasource": { + "type": "postgres", + "uid": "abc123" + }, + "targets": [ + { + "expr": "go_goroutines{job=\"$job\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + }, + { + "exemplar": true, + "expr": "query2", + "interval": "", + "legendFormat": "", + "refId": "B" + } + ], + "title": "Panel Title", + "type": "timeseries" + } + ], + "schemaVersion": 35 +}` + dashboardWithQueries = ` { "panels": [ @@ -256,6 +287,24 @@ func TestGetUniqueDashboardDatasourceUids(t *testing.T) { } func TestGroupQueriesByPanelId(t *testing.T) { + t.Run("can extract queries from dashboard with panel datasource string that has no datasource on panel targets", func(t *testing.T) { + json, err := simplejson.NewJson([]byte(oldStyleDashboard)) + require.NoError(t, err) + queries := GroupQueriesByPanelId(json) + + panelId := int64(2) + queriesByDatasource := GroupQueriesByDataSource(queries[panelId]) + require.Len(t, queriesByDatasource[0], 1) + }) + t.Run("can extract queries from dashboard with panel json datasource that has no datasource on panel targets", func(t *testing.T) { + json, err := simplejson.NewJson([]byte(dashboardWithTargetsWithNoDatasources)) + require.NoError(t, err) + queries := GroupQueriesByPanelId(json) + + panelId := int64(2) + queriesByDatasource := GroupQueriesByDataSource(queries[panelId]) + require.Len(t, queriesByDatasource[0], 2) + }) t.Run("can extract no queries from empty dashboard", func(t *testing.T) { json, err := simplejson.NewJson([]byte(`{"panels": {}}`)) require.NoError(t, err) @@ -321,7 +370,10 @@ func TestGroupQueriesByPanelId(t *testing.T) { query, err := queries[2][0].MarshalJSON() require.NoError(t, err) require.JSONEq(t, `{ - "datasource": "_yxMP8Ynk", + "datasource": { + "uid": "_yxMP8Ynk", + "type": "public-ds" + }, "exemplar": true, "expr": "go_goroutines{job=\"$job\"}", "interval": "",