PublicDashboards: Do not return hidden queries (#72554)

* PublicDashboards: Do not return hidden queries

* Update pkg/services/publicdashboards/service/query_test.go

Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>

---------

Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
This commit is contained in:
Ezequiel Victorero 2023-07-31 10:54:54 -03:00 committed by GitHub
parent 117e334719
commit bffd55efd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 17 deletions

View File

@ -8,6 +8,7 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/expr"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/annotations"
"github.com/grafana/grafana/pkg/services/dashboards"
@ -280,11 +281,19 @@ func extractQueriesFromPanels(panels []interface{}, result map[int64][]*simplejs
}
var panelQueries []*simplejson.Json
hasExpression := panelHasAnExpression(panel)
for _, queryObj := range panel.Get("targets").MustArray() {
query := simplejson.NewFromAny(queryObj)
// We dont support exemplars for public dashboards currently
// it the panel doesn't have an expression and the query is disabled (hide is true), skip the query
// the expression handler will take care later of removing hidden queries which could be necessary to calculate
// the value of other queries
if !hasExpression && query.Get("hide").MustBool() {
continue
}
// We don't support exemplars for public dashboards currently
query.Del("exemplar")
// if query target has no datasource, set it to have the datasource on the panel
@ -300,6 +309,17 @@ func extractQueriesFromPanels(panels []interface{}, result map[int64][]*simplejs
}
}
func panelHasAnExpression(panel *simplejson.Json) bool {
var hasExpression bool
for _, queryObj := range panel.Get("targets").MustArray() {
query := simplejson.NewFromAny(queryObj)
if expr.NodeTypeFromDatasourceUID(getDataSourceUidFromJson(query)) == expr.TypeCMDNode {
hasExpression = true
}
}
return hasExpression
}
func getDataSourceUidFromJson(query *simplejson.Json) string {
uid := query.Get("datasource").Get("uid").MustString()

View File

@ -321,6 +321,16 @@ const (
"interval": "",
"legendFormat": "",
"refId": "B"
},
{
"datasource": {
"name": "Expression",
"type": "__expr__",
"uid": "__expr__"
},
"expression": "$A + $B",
"refId": "C",
"type": "math"
}
],
"title": "Panel Title",
@ -358,6 +368,16 @@ const (
"legendFormat": "",
"refId": "B",
"hide": true
},
{
"datasource": {
"name": "Expression",
"type": "__expr__",
"uid": "__expr__"
},
"expression": "$A + $B",
"refId": "C",
"type": "math"
}
],
"title": "Panel Title",
@ -367,7 +387,7 @@ const (
"schemaVersion": 35
}`
dashboardWithRows = `
dashboardWithRowsAndOneHiddenQuery = `
{
"panels": [
{
@ -393,6 +413,7 @@ const (
"expr": "query2",
"interval": "",
"legendFormat": "",
"hide": true,
"refId": "B"
}
],
@ -684,8 +705,9 @@ func TestGetQueryDataResponse(t *testing.T) {
t.Run("Returns query data even when the query is hidden", func(t *testing.T) {
hiddenQuery := map[string]interface{}{
"datasource": map[string]interface{}{
"type": "mysql",
"uid": "ds1",
"name": "Expression",
"type": "__expr__",
"uid": "__expr__",
},
"hide": true,
"refId": "A",
@ -1339,18 +1361,12 @@ func TestBuildMetricRequest(t *testing.T) {
require.Equal(t, publicDashboardQueryDTO.MaxDataPoints, reqDTO.Queries[i].Get("maxDataPoints").MustInt64())
}
require.Len(t, reqDTO.Queries, 2)
require.Equal(
t,
simplejson.NewFromAny(hiddenQuery),
reqDTO.Queries[0],
)
require.Len(t, reqDTO.Queries, 1)
require.Equal(
t,
simplejson.NewFromAny(nonHiddenQuery),
reqDTO.Queries[1],
reqDTO.Queries[0],
)
})
}
@ -1484,24 +1500,24 @@ func TestGroupQueriesByPanelId(t *testing.T) {
}`, string(query))
})
t.Run("hidden query not filtered", func(t *testing.T) {
t.Run("hidden queries in a panel with an expression not filtered", func(t *testing.T) {
json, err := simplejson.NewJson([]byte(dashboardWithOneHiddenQuery))
require.NoError(t, err)
queries := groupQueriesByPanelId(json)[2]
require.Len(t, queries, 2)
require.Len(t, queries, 3)
})
t.Run("hidden queries not filtered, so queries returned", func(t *testing.T) {
t.Run("all hidden queries in a panel with an expression not filtered", func(t *testing.T) {
json, err := simplejson.NewJson([]byte(dashboardWithAllHiddenQueries))
require.NoError(t, err)
queries := groupQueriesByPanelId(json)[2]
require.Len(t, queries, 2)
require.Len(t, queries, 3)
})
t.Run("queries inside panels inside rows are returned", func(t *testing.T) {
json, err := simplejson.NewJson([]byte(dashboardWithRows))
json, err := simplejson.NewJson([]byte(dashboardWithRowsAndOneHiddenQuery))
require.NoError(t, err)
queries := groupQueriesByPanelId(json)
@ -1511,6 +1527,20 @@ func TestGroupQueriesByPanelId(t *testing.T) {
assert.Len(t, queries, 2)
})
t.Run("hidden queries are not returned", func(t *testing.T) {
json, err := simplejson.NewJson([]byte(dashboardWithRowsAndOneHiddenQuery))
require.NoError(t, err)
queries := groupQueriesByPanelId(json)
var totalQueries int
for idx := range queries {
totalQueries += len(queries[idx])
assert.NotNil(t, queries[idx])
}
assert.Equal(t, 3, totalQueries)
})
}
func TestGroupQueriesByDataSource(t *testing.T) {