mirror of
https://github.com/grafana/grafana.git
synced 2024-12-28 18:01:40 -06:00
Search: Make the existing dashboard parsing code public (#95649)
This commit is contained in:
parent
ed52515ae3
commit
7f560c13e4
@ -112,12 +112,15 @@ func newDatasourceVariableLookup(dsLookup DatasourceLookup) *datasourceVariableL
|
||||
}
|
||||
}
|
||||
|
||||
// nolint:gocyclo
|
||||
// ReadDashboard will take a byte stream and return dashboard info
|
||||
func readDashboard(stream io.Reader, lookup DatasourceLookup) (*dashboardInfo, error) {
|
||||
dash := &dashboardInfo{}
|
||||
|
||||
func ReadDashboard(stream io.Reader, lookup DatasourceLookup) (*DashboardSummaryInfo, error) {
|
||||
iter := jsoniter.Parse(jsoniter.ConfigDefault, stream, 1024)
|
||||
return readDashboardIter(iter, lookup)
|
||||
}
|
||||
|
||||
// nolint:gocyclo
|
||||
func readDashboardIter(iter *jsoniter.Iterator, lookup DatasourceLookup) (*DashboardSummaryInfo, error) {
|
||||
dash := &DashboardSummaryInfo{}
|
||||
|
||||
datasourceVariablesLookup := newDatasourceVariableLookup(lookup)
|
||||
|
||||
@ -129,6 +132,14 @@ func readDashboard(stream io.Reader, lookup DatasourceLookup) (*dashboardInfo, e
|
||||
}
|
||||
|
||||
switch l1Field {
|
||||
// k8s metadata wrappers (skip)
|
||||
case "metadata", "kind", "apiVersion":
|
||||
_ = iter.Read()
|
||||
|
||||
// recursively read the spec as dashboard json
|
||||
case "spec":
|
||||
return readDashboardIter(iter, lookup)
|
||||
|
||||
case "id":
|
||||
dash.ID = iter.ReadInt64()
|
||||
|
||||
@ -268,7 +279,12 @@ func readDashboard(stream io.Reader, lookup DatasourceLookup) (*dashboardInfo, e
|
||||
filterOutSpecialDatasources(dash)
|
||||
|
||||
targets := newTargetInfo(lookup)
|
||||
for _, panel := range dash.Panels {
|
||||
for idx, panel := range dash.Panels {
|
||||
if panel.Type == "row" {
|
||||
dash.Panels[idx].Datasource = nil
|
||||
continue
|
||||
}
|
||||
|
||||
targets.addPanel(panel)
|
||||
}
|
||||
dash.Datasource = targets.GetDatasourceInfo()
|
||||
@ -276,13 +292,13 @@ func readDashboard(stream io.Reader, lookup DatasourceLookup) (*dashboardInfo, e
|
||||
return dash, iter.Error
|
||||
}
|
||||
|
||||
func panelRequiresDatasource(panel panelInfo) bool {
|
||||
func panelRequiresDatasource(panel PanelSummaryInfo) bool {
|
||||
return panel.Type != "row"
|
||||
}
|
||||
|
||||
func fillDefaultDatasources(dash *dashboardInfo, lookup DatasourceLookup) {
|
||||
func fillDefaultDatasources(dash *DashboardSummaryInfo, lookup DatasourceLookup) {
|
||||
for i, panel := range dash.Panels {
|
||||
if len(panel.Datasource) != 0 || !panelRequiresDatasource(panel) {
|
||||
if len(panel.Datasource) != 0 || !panelRequiresDatasource(PanelSummaryInfo{}) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -293,7 +309,7 @@ func fillDefaultDatasources(dash *dashboardInfo, lookup DatasourceLookup) {
|
||||
}
|
||||
}
|
||||
|
||||
func filterOutSpecialDatasources(dash *dashboardInfo) {
|
||||
func filterOutSpecialDatasources(dash *DashboardSummaryInfo) {
|
||||
for i, panel := range dash.Panels {
|
||||
var dsRefs []DataSourceRef
|
||||
|
||||
@ -315,7 +331,7 @@ func filterOutSpecialDatasources(dash *dashboardInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
func replaceDatasourceVariables(dash *dashboardInfo, datasourceVariablesLookup *datasourceVariableLookup) {
|
||||
func replaceDatasourceVariables(dash *DashboardSummaryInfo, datasourceVariablesLookup *datasourceVariableLookup) {
|
||||
for i, panel := range dash.Panels {
|
||||
var dsVariableRefs []DataSourceRef
|
||||
var dsRefs []DataSourceRef
|
||||
@ -362,8 +378,8 @@ func findDatasourceRefsForVariables(dsVariableRefs []DataSourceRef, datasourceVa
|
||||
}
|
||||
|
||||
// will always return strings for now
|
||||
func readpanelInfo(iter *jsoniter.Iterator, lookup DatasourceLookup) panelInfo {
|
||||
panel := panelInfo{}
|
||||
func readpanelInfo(iter *jsoniter.Iterator, lookup DatasourceLookup) PanelSummaryInfo {
|
||||
panel := PanelSummaryInfo{}
|
||||
|
||||
targets := newTargetInfo(lookup)
|
||||
|
||||
|
@ -71,6 +71,7 @@ func TestReadDashboard(t *testing.T) {
|
||||
"special-datasource-types",
|
||||
"panels-without-datasources",
|
||||
"panel-with-library-panel-field",
|
||||
"k8s-wrapper",
|
||||
}
|
||||
|
||||
devdash := "../../../../../devenv/dev-dashboards/"
|
||||
@ -89,7 +90,7 @@ func TestReadDashboard(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
dash, err := readDashboard(f, dsLookupForTests())
|
||||
dash, err := ReadDashboard(f, dsLookupForTests())
|
||||
sortDatasources(dash)
|
||||
|
||||
require.NoError(t, err)
|
||||
@ -114,7 +115,7 @@ func TestReadDashboard(t *testing.T) {
|
||||
}
|
||||
|
||||
// assure consistent ordering of datasources to prevent random failures of `assert.JSONEq`
|
||||
func sortDatasources(dash *dashboardInfo) {
|
||||
func sortDatasources(dash *DashboardSummaryInfo) {
|
||||
sort.Slice(dash.Datasource, func(i, j int) bool {
|
||||
return strings.Compare(dash.Datasource[i].UID, dash.Datasource[j].UID) > 0
|
||||
})
|
||||
|
@ -40,7 +40,7 @@ func NewStaticDashboardSummaryBuilder(lookup DatasourceLookup, sanitize bool) en
|
||||
Fields: make(map[string]string),
|
||||
}
|
||||
stream := bytes.NewBuffer(body)
|
||||
dash, err := readDashboard(stream, lookup)
|
||||
dash, err := ReadDashboard(stream, lookup)
|
||||
if err != nil {
|
||||
summary.Error = &entity.EntityErrorInfo{
|
||||
Message: err.Error(),
|
||||
@ -74,7 +74,7 @@ func NewStaticDashboardSummaryBuilder(lookup DatasourceLookup, sanitize bool) en
|
||||
}
|
||||
|
||||
// panelSummary take panel info and returns entity summaries for the given panel and all its collapsed panels.
|
||||
func panelSummary(panel panelInfo, uid string, dashboardRefs ReferenceAccumulator) []*entity.EntitySummary {
|
||||
func panelSummary(panel PanelSummaryInfo, uid string, dashboardRefs ReferenceAccumulator) []*entity.EntitySummary {
|
||||
panels := []*entity.EntitySummary{}
|
||||
|
||||
panelRefs := NewReferenceAccumulator()
|
||||
|
@ -82,7 +82,7 @@ func (s *targetInfo) addTarget(iter *jsoniter.Iterator) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *targetInfo) addPanel(panel panelInfo) {
|
||||
func (s *targetInfo) addPanel(panel PanelSummaryInfo) {
|
||||
for idx, v := range panel.Datasource {
|
||||
if v.UID != "" {
|
||||
s.uids[v.UID] = &panel.Datasource[idx]
|
||||
|
74
pkg/services/store/kind/dashboard/testdata/k8s-wrapper-info.json
vendored
Normal file
74
pkg/services/store/kind/dashboard/testdata/k8s-wrapper-info.json
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
{
|
||||
"id": 141,
|
||||
"title": "pppp",
|
||||
"tags": null,
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "green pie",
|
||||
"libraryPanel": "a7975b7a-fb53-4ab7-951d-15810953b54f",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "green pie",
|
||||
"libraryPanel": "e1d5f519-dabd-47c6-9ad7-83d181ce1cee",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"title": "",
|
||||
"type": "barchart",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"title": "",
|
||||
"type": "graph",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "collapsed row",
|
||||
"type": "row",
|
||||
"collapsed": [
|
||||
{
|
||||
"id": 42,
|
||||
"title": "blue pie",
|
||||
"libraryPanel": "l3d2s634-fdgf-75u4-3fg3-67j966ii7jur"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 38,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
122
pkg/services/store/kind/dashboard/testdata/k8s-wrapper.json
vendored
Normal file
122
pkg/services/store/kind/dashboard/testdata/k8s-wrapper.json
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
{
|
||||
"kind": "Dashboard",
|
||||
"apiVersion": "dashboard.grafana.app/v0alpha1",
|
||||
"metadata": {
|
||||
"name": "adfbg6f",
|
||||
"namespace": "default",
|
||||
"uid": "b396894e-56bf-4a01-837b-64157912ca00",
|
||||
"creationTimestamp": "2024-10-30T18:30:54Z",
|
||||
"annotations": {
|
||||
"grafana.app/createdBy": "user:be2g71ke8yoe8b",
|
||||
"grafana.app/originHash": "Grafana v9.2.0 (NA)",
|
||||
"grafana.app/originName": "UI",
|
||||
"grafana.app/originPath": "/dashboard/new"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 141,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"libraryPanel": {
|
||||
"name": "green pie",
|
||||
"uid": "a7975b7a-fb53-4ab7-951d-15810953b54f"
|
||||
},
|
||||
"title": "green pie"
|
||||
},
|
||||
{
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"libraryPanel": {
|
||||
"name": "red pie",
|
||||
"uid": "e1d5f519-dabd-47c6-9ad7-83d181ce1cee"
|
||||
},
|
||||
"title": "green pie"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"type": "barchart"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "graph"
|
||||
},
|
||||
{
|
||||
"collapsed": true,
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 9
|
||||
},
|
||||
"id": 3,
|
||||
"panels": [
|
||||
{
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 0
|
||||
},
|
||||
"id": 42,
|
||||
"libraryPanel": {
|
||||
"name": "blue pie",
|
||||
"uid": "l3d2s634-fdgf-75u4-3fg3-67j966ii7jur"
|
||||
},
|
||||
"title": "blue pie"
|
||||
}
|
||||
],
|
||||
"title": "collapsed row",
|
||||
"type": "row"
|
||||
}
|
||||
],
|
||||
"refresh": "",
|
||||
"schemaVersion": 38,
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "pppp",
|
||||
"uid": "adfbg6f",
|
||||
"version": 3,
|
||||
"weekStart": ""
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package dashboard
|
||||
|
||||
type panelInfo struct {
|
||||
type PanelSummaryInfo struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description,omitempty"`
|
||||
@ -10,23 +10,23 @@ type panelInfo struct {
|
||||
Datasource []DataSourceRef `json:"datasource,omitempty"` // UIDs
|
||||
Transformer []string `json:"transformer,omitempty"` // ids of the transformation steps
|
||||
// Rows define panels as sub objects
|
||||
Collapsed []panelInfo `json:"collapsed,omitempty"`
|
||||
Collapsed []PanelSummaryInfo `json:"collapsed,omitempty"`
|
||||
}
|
||||
|
||||
type dashboardInfo struct {
|
||||
UID string `json:"uid,omitempty"`
|
||||
ID int64 `json:"id,omitempty"` // internal ID
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Tags []string `json:"tags"`
|
||||
TemplateVars []string `json:"templateVars,omitempty"` // the keys used
|
||||
Datasource []DataSourceRef `json:"datasource,omitempty"` // UIDs
|
||||
Panels []panelInfo `json:"panels"` // nesed documents
|
||||
SchemaVersion int64 `json:"schemaVersion"`
|
||||
LinkCount int64 `json:"linkCount"`
|
||||
TimeFrom string `json:"timeFrom"`
|
||||
TimeTo string `json:"timeTo"`
|
||||
TimeZone string `json:"timezone"`
|
||||
Refresh string `json:"refresh,omitempty"`
|
||||
ReadOnly bool `json:"readOnly,omitempty"` // editable = false
|
||||
type DashboardSummaryInfo struct {
|
||||
UID string `json:"uid,omitempty"`
|
||||
ID int64 `json:"id,omitempty"` // internal ID
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Tags []string `json:"tags"`
|
||||
TemplateVars []string `json:"templateVars,omitempty"` // the keys used
|
||||
Datasource []DataSourceRef `json:"datasource,omitempty"` // UIDs
|
||||
Panels []PanelSummaryInfo `json:"panels"` // nesed documents
|
||||
SchemaVersion int64 `json:"schemaVersion"`
|
||||
LinkCount int64 `json:"linkCount"`
|
||||
TimeFrom string `json:"timeFrom"`
|
||||
TimeTo string `json:"timeTo"`
|
||||
TimeZone string `json:"timezone"`
|
||||
Refresh string `json:"refresh,omitempty"`
|
||||
ReadOnly bool `json:"readOnly,omitempty"` // editable = false
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user