PublicDashboards: Fix hidden queries execution (#57004)

PublicDashboards: Fix hidden queries execution
This commit is contained in:
juanicabanas
2022-10-18 10:47:24 -03:00
committed by GitHub
parent ed98d7bc27
commit 71f79b9de0
4 changed files with 325 additions and 61 deletions

View File

@@ -46,17 +46,19 @@ func GroupQueriesByPanelId(dashboard *simplejson.Json) map[int64][]*simplejson.J
for _, queryObj := range panel.Get("targets").MustArray() {
query := simplejson.NewFromAny(queryObj)
// We dont support exemplars for public dashboards currently
query.Del("exemplar")
if hideAttr, exists := query.CheckGet("hide"); !exists || !hideAttr.MustBool() {
// We dont support exemplars for public dashboards currently
query.Del("exemplar")
// if query target has no datasource, set it to have the datasource on the panel
if _, ok := query.CheckGet("datasource"); !ok {
uid := GetDataSourceUidFromJson(panel)
datasource := map[string]interface{}{"type": "public-ds", "uid": uid}
query.Set("datasource", datasource)
// if query target has no datasource, set it to have the datasource on the panel
if _, ok := query.CheckGet("datasource"); !ok {
uid := GetDataSourceUidFromJson(panel)
datasource := map[string]interface{}{"type": "public-ds", "uid": uid}
query.Set("datasource", datasource)
}
panelQueries = append(panelQueries, query)
}
panelQueries = append(panelQueries, query)
}
result[panel.Get("id").MustInt64()] = panelQueries

View File

@@ -303,6 +303,80 @@ const (
],
"schemaVersion": 21
}`
dashboardWithOneHiddenQuery = `
{
"panels": [
{
"id": 2,
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "_yxMP8Ynk"
},
"exemplar": true,
"expr": "go_goroutines{job=\"$job\"}",
"interval": "",
"legendFormat": "",
"refId": "A",
"hide": true
},
{
"datasource": {
"type": "prometheus",
"uid": "promds2"
},
"exemplar": true,
"expr": "query2",
"interval": "",
"legendFormat": "",
"refId": "B"
}
],
"title": "Panel Title",
"type": "timeseries"
}
],
"schemaVersion": 35
}`
dashboardWithAllHiddenQueries = `
{
"panels": [
{
"id": 2,
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "_yxMP8Ynk"
},
"exemplar": true,
"expr": "go_goroutines{job=\"$job\"}",
"interval": "",
"legendFormat": "",
"refId": "A",
"hide": true
},
{
"datasource": {
"type": "prometheus",
"uid": "promds2"
},
"exemplar": true,
"expr": "query2",
"interval": "",
"legendFormat": "",
"refId": "B",
"hide": true
}
],
"title": "Panel Title",
"type": "timeseries"
}
],
"schemaVersion": 35
}`
)
func TestGetUniqueDashboardDatasourceUids(t *testing.T) {
@@ -458,6 +532,27 @@ func TestGroupQueriesByPanelId(t *testing.T) {
"refId": "A"
}`, string(query))
})
t.Run("hidden query filtered", func(t *testing.T) {
json, err := simplejson.NewJson([]byte(dashboardWithOneHiddenQuery))
require.NoError(t, err)
queries := GroupQueriesByPanelId(json)[2]
require.Len(t, queries, 1)
for _, query := range queries {
if hideAttr, exists := query.CheckGet("hide"); exists && hideAttr.MustBool() {
require.Fail(t, "hidden queries should have been filtered")
}
}
})
t.Run("hidden query filtered, so empty queries returned", func(t *testing.T) {
json, err := simplejson.NewJson([]byte(dashboardWithAllHiddenQueries))
require.NoError(t, err)
queries := GroupQueriesByPanelId(json)[2]
require.Len(t, queries, 0)
})
}
func TestGroupQueriesByDataSource(t *testing.T) {

View File

@@ -213,6 +213,10 @@ func (pd *PublicDashboardServiceImpl) GetQueryDataResponse(ctx context.Context,
return nil, err
}
if len(metricReq.Queries) == 0 {
return nil, nil
}
anonymousUser := pd.BuildAnonymousUser(ctx, dashboard)
res, err := pd.QueryDataService.QueryData(ctx, anonymousUser, skipCache, metricReq)

View File

@@ -120,7 +120,7 @@ func TestSavePublicDashboard(t *testing.T) {
sqlStore := sqlstore.InitTestDB(t)
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg))
publicdashboardStore := database.ProvideStore(sqlStore)
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil)
service := &PublicDashboardServiceImpl{
log: log.New("test.logger"),
@@ -164,7 +164,7 @@ func TestSavePublicDashboard(t *testing.T) {
sqlStore := sqlstore.InitTestDB(t)
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg))
publicdashboardStore := database.ProvideStore(sqlStore)
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil)
service := &PublicDashboardServiceImpl{
log: log.New("test.logger"),
@@ -195,7 +195,7 @@ func TestSavePublicDashboard(t *testing.T) {
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg))
publicdashboardStore := database.ProvideStore(sqlStore)
templateVars := make([]map[string]interface{}, 1)
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, templateVars)
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, templateVars, nil)
service := &PublicDashboardServiceImpl{
log: log.New("test.logger"),
@@ -255,7 +255,7 @@ func TestUpdatePublicDashboard(t *testing.T) {
sqlStore := sqlstore.InitTestDB(t)
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg))
publicdashboardStore := database.ProvideStore(sqlStore)
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil)
service := &PublicDashboardServiceImpl{
log: log.New("test.logger"),
@@ -316,7 +316,7 @@ func TestUpdatePublicDashboard(t *testing.T) {
sqlStore := sqlstore.InitTestDB(t)
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg))
publicdashboardStore := database.ProvideStore(sqlStore)
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil)
service := &PublicDashboardServiceImpl{
log: log.New("test.logger"),
@@ -365,7 +365,7 @@ func TestUpdatePublicDashboard(t *testing.T) {
func TestBuildAnonymousUser(t *testing.T) {
sqlStore := sqlstore.InitTestDB(t)
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg))
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil)
publicdashboardStore := database.ProvideStore(sqlStore)
service := &PublicDashboardServiceImpl{
log: log.New("test.logger"),
@@ -386,7 +386,7 @@ func TestGetMetricRequest(t *testing.T) {
sqlStore := sqlstore.InitTestDB(t)
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg))
publicdashboardStore := database.ProvideStore(sqlStore)
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil)
publicDashboard := &PublicDashboard{
Uid: "1",
DashboardUid: dashboard.Uid,
@@ -425,13 +425,67 @@ func TestGetMetricRequest(t *testing.T) {
})
}
func TestGetQueryDataResponse(t *testing.T) {
sqlStore := sqlstore.InitTestDB(t)
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg))
publicdashboardStore := database.ProvideStore(sqlStore)
service := &PublicDashboardServiceImpl{
log: log.New("test.logger"),
store: publicdashboardStore,
intervalCalculator: intervalv2.NewCalculator(),
}
publicDashboardQueryDTO := PublicDashboardQueryDTO{
IntervalMs: int64(1),
MaxDataPoints: int64(1),
}
t.Run("Returns nil when query is hidden", func(t *testing.T) {
hiddenQuery := map[string]interface{}{
"datasource": map[string]interface{}{
"type": "mysql",
"uid": "ds1",
},
"hide": true,
"refId": "A",
}
customPanels := []interface{}{
map[string]interface{}{
"id": 1,
"datasource": map[string]interface{}{
"uid": "ds1",
},
"targets": []interface{}{hiddenQuery},
}}
dashboard := insertTestDashboard(t, dashboardStore, "testDashWithHiddenQuery", 1, 0, true, []map[string]interface{}{}, customPanels)
dto := &SavePublicDashboardConfigDTO{
DashboardUid: dashboard.Uid,
OrgId: dashboard.OrgId,
UserId: 7,
PublicDashboard: &PublicDashboard{
IsEnabled: true,
DashboardUid: "NOTTHESAME",
OrgId: 9999999,
TimeSettings: timeSettings,
},
}
pubdashDto, err := service.SavePublicDashboardConfig(context.Background(), SignedInUser, dto)
require.NoError(t, err)
resp, _ := service.GetQueryDataResponse(context.Background(), true, publicDashboardQueryDTO, 1, pubdashDto.AccessToken)
require.Nil(t, resp)
})
}
func TestBuildMetricRequest(t *testing.T) {
sqlStore := sqlstore.InitTestDB(t)
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg))
publicdashboardStore := database.ProvideStore(sqlStore)
publicDashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
nonPublicDashboard := insertTestDashboard(t, dashboardStore, "testNonPublicDashie", 1, 0, true, []map[string]interface{}{})
publicDashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil)
nonPublicDashboard := insertTestDashboard(t, dashboardStore, "testNonPublicDashie", 1, 0, true, []map[string]interface{}{}, nil)
from, to := internal.GetTimeRangeFromDashboard(t, publicDashboard.Data)
service := &PublicDashboardServiceImpl{
@@ -533,58 +587,167 @@ func TestBuildMetricRequest(t *testing.T) {
require.ErrorContains(t, err, ErrPublicDashboardPanelNotFound.Reason)
})
t.Run("metric request built without hidden query", func(t *testing.T) {
hiddenQuery := map[string]interface{}{
"datasource": map[string]interface{}{
"type": "mysql",
"uid": "ds1",
},
"hide": true,
"refId": "A",
}
nonHiddenQuery := map[string]interface{}{
"datasource": map[string]interface{}{
"type": "prometheus",
"uid": "ds2",
},
"refId": "B",
}
customPanels := []interface{}{
map[string]interface{}{
"id": 1,
"datasource": map[string]interface{}{
"uid": "ds1",
},
"targets": []interface{}{hiddenQuery, nonHiddenQuery},
}}
publicDashboard := insertTestDashboard(t, dashboardStore, "testDashWithHiddenQuery", 1, 0, true, []map[string]interface{}{}, customPanels)
reqDTO, err := service.buildMetricRequest(
context.Background(),
publicDashboard,
publicDashboardPD,
1,
publicDashboardQueryDTO,
)
require.NoError(t, err)
require.Equal(t, from, reqDTO.From)
require.Equal(t, to, reqDTO.To)
for i := range reqDTO.Queries {
require.Equal(t, publicDashboardQueryDTO.IntervalMs, reqDTO.Queries[i].Get("intervalMs").MustInt64())
require.Equal(t, publicDashboardQueryDTO.MaxDataPoints, reqDTO.Queries[i].Get("maxDataPoints").MustInt64())
}
require.Len(t, reqDTO.Queries, 1)
require.NotEqual(
t,
simplejson.NewFromAny(hiddenQuery),
reqDTO.Queries[0],
)
require.Equal(
t,
simplejson.NewFromAny(nonHiddenQuery),
reqDTO.Queries[0],
)
})
t.Run("metric request built with 0 queries len when all queries are hidden", func(t *testing.T) {
customPanels := []interface{}{
map[string]interface{}{
"id": 1,
"datasource": map[string]interface{}{
"uid": "ds1",
},
"targets": []interface{}{map[string]interface{}{
"datasource": map[string]interface{}{
"type": "mysql",
"uid": "ds1",
},
"hide": true,
"refId": "A",
}, map[string]interface{}{
"datasource": map[string]interface{}{
"type": "prometheus",
"uid": "ds2",
},
"hide": true,
"refId": "B",
}},
}}
publicDashboard := insertTestDashboard(t, dashboardStore, "testDashWithAllQueriesHidden", 1, 0, true, []map[string]interface{}{}, customPanels)
reqDTO, err := service.buildMetricRequest(
context.Background(),
publicDashboard,
publicDashboardPD,
1,
publicDashboardQueryDTO,
)
require.NoError(t, err)
require.Equal(t, from, reqDTO.From)
require.Equal(t, to, reqDTO.To)
require.Len(t, reqDTO.Queries, 0)
})
}
func insertTestDashboard(t *testing.T, dashboardStore *dashboardsDB.DashboardStore, title string, orgId int64,
folderId int64, isFolder bool, templateVars []map[string]interface{}, tags ...interface{}) *models.Dashboard {
folderId int64, isFolder bool, templateVars []map[string]interface{}, customPanels []interface{}, tags ...interface{}) *models.Dashboard {
t.Helper()
var dashboardPanels []interface{}
if customPanels != nil {
dashboardPanels = customPanels
} else {
dashboardPanels = []interface{}{
map[string]interface{}{
"id": 1,
"datasource": map[string]interface{}{
"uid": "ds1",
},
"targets": []interface{}{
map[string]interface{}{
"datasource": map[string]interface{}{
"type": "mysql",
"uid": "ds1",
},
"refId": "A",
},
map[string]interface{}{
"datasource": map[string]interface{}{
"type": "prometheus",
"uid": "ds2",
},
"refId": "B",
},
},
},
map[string]interface{}{
"id": 2,
"datasource": map[string]interface{}{
"uid": "ds3",
},
"targets": []interface{}{
map[string]interface{}{
"datasource": map[string]interface{}{
"type": "mysql",
"uid": "ds3",
},
"refId": "C",
},
},
},
}
}
cmd := models.SaveDashboardCommand{
OrgId: orgId,
FolderId: folderId,
IsFolder: isFolder,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": title,
"tags": tags,
"panels": []interface{}{
map[string]interface{}{
"id": 1,
"datasource": map[string]interface{}{
"uid": "ds1",
},
"targets": []interface{}{
map[string]interface{}{
"datasource": map[string]interface{}{
"type": "mysql",
"uid": "ds1",
},
"refId": "A",
},
map[string]interface{}{
"datasource": map[string]interface{}{
"type": "prometheus",
"uid": "ds2",
},
"refId": "B",
},
},
},
map[string]interface{}{
"id": 2,
"datasource": map[string]interface{}{
"uid": "ds3",
},
"targets": []interface{}{
map[string]interface{}{
"datasource": map[string]interface{}{
"type": "mysql",
"uid": "ds3",
},
"refId": "C",
},
},
},
},
"id": nil,
"title": title,
"tags": tags,
"panels": dashboardPanels,
"templating": map[string]interface{}{
"list": templateVars,
},