From 85af8ce2ec6f1e87d6fea17d33c66891a3cc6760 Mon Sep 17 00:00:00 2001 From: Jesse Weaver Date: Mon, 16 May 2022 13:08:42 -0600 Subject: [PATCH] [Public Dashboards] Extract queries from dashboards (#48602) --- pkg/models/dashboard_queries.go | 29 ++++++ pkg/models/dashboard_queries_test.go | 132 +++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 pkg/models/dashboard_queries.go create mode 100644 pkg/models/dashboard_queries_test.go diff --git a/pkg/models/dashboard_queries.go b/pkg/models/dashboard_queries.go new file mode 100644 index 00000000000..8aa3ed6ebd9 --- /dev/null +++ b/pkg/models/dashboard_queries.go @@ -0,0 +1,29 @@ +package models + +import ( + "github.com/grafana/grafana/pkg/components/simplejson" +) + +func GetQueriesFromDashboard(dashboard *simplejson.Json) map[int64][]*simplejson.Json { + result := make(map[int64][]*simplejson.Json) + + for _, panelObj := range dashboard.Get("panels").MustArray() { + panel := simplejson.NewFromAny(panelObj) + + var panelQueries []*simplejson.Json + + for _, queryObj := range panel.Get("targets").MustArray() { + query := simplejson.NewFromAny(queryObj) + + if _, ok := query.CheckGet("datasource"); !ok { + query.Set("datasource", panel.Get("datasource")) + } + + panelQueries = append(panelQueries, query) + } + + result[panel.Get("id").MustInt64()] = panelQueries + } + + return result +} diff --git a/pkg/models/dashboard_queries_test.go b/pkg/models/dashboard_queries_test.go new file mode 100644 index 00000000000..a26ee0e50ce --- /dev/null +++ b/pkg/models/dashboard_queries_test.go @@ -0,0 +1,132 @@ +package models + +import ( + "testing" + + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/stretchr/testify/require" +) + +const ( + dashboardWithNoQueries = ` +{ + "panels": [ + { + "id": 2, + "title": "Panel Title", + "type": "timeseries" + } + ], + "schemaVersion": 35 +}` + + dashboardWithQueries = ` +{ + "panels": [ + { + "id": 2, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "_yxMP8Ynk" + }, + "exemplar": true, + "expr": "go_goroutines{job=\"$job\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Panel Title", + "type": "timeseries" + } + ], + "schemaVersion": 35 +}` + + oldStyleDashboard = ` +{ + "panels": [ + { + "datasource": "_yxMP8Ynk", + "id": 2, + "targets": [ + { + "exemplar": true, + "expr": "go_goroutines{job=\"$job\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Panel Title", + "type": "timeseries" + } + ], + "schemaVersion": 21 +}` +) + +func TestGetQueriesFromDashboard(t *testing.T) { + t.Run("can extract no queries from empty dashboard", func(t *testing.T) { + json, err := simplejson.NewJson([]byte(`{"panels": {}}`)) + require.NoError(t, err) + + queries := GetQueriesFromDashboard(json) + require.Len(t, queries, 0) + }) + + t.Run("can extract no queries from empty panel", func(t *testing.T) { + json, err := simplejson.NewJson([]byte(dashboardWithNoQueries)) + require.NoError(t, err) + + queries := GetQueriesFromDashboard(json) + require.Len(t, queries, 1) + require.Contains(t, queries, int64(2)) + require.Len(t, queries[2], 0) + }) + + t.Run("can extract queries from panels", func(t *testing.T) { + json, err := simplejson.NewJson([]byte(dashboardWithQueries)) + require.NoError(t, err) + + queries := GetQueriesFromDashboard(json) + require.Len(t, queries, 1) + require.Contains(t, queries, int64(2)) + require.Len(t, queries[2], 1) + query, err := queries[2][0].MarshalJSON() + require.NoError(t, err) + require.JSONEq(t, `{ + "datasource": { + "type": "prometheus", + "uid": "_yxMP8Ynk" + }, + "exemplar": true, + "expr": "go_goroutines{job=\"$job\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + }`, string(query)) + }) + + t.Run("can extract queries from old-style panels", func(t *testing.T) { + json, err := simplejson.NewJson([]byte(oldStyleDashboard)) + require.NoError(t, err) + + queries := GetQueriesFromDashboard(json) + require.Len(t, queries, 1) + require.Contains(t, queries, int64(2)) + require.Len(t, queries[2], 1) + query, err := queries[2][0].MarshalJSON() + require.NoError(t, err) + require.JSONEq(t, `{ + "datasource": "_yxMP8Ynk", + "exemplar": true, + "expr": "go_goroutines{job=\"$job\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + }`, string(query)) + }) +}