Skip to content

Commit 00edde0

Browse files
authored
Support a datasource which may be a map (#190)
In recent versions of Grafana the datasource can be either a string or a map with entries for type and uid. Support both of these cases by using an interface which will allow backwards compatiblity.
1 parent a80b27b commit 00edde0

File tree

4 files changed

+201
-26
lines changed

4 files changed

+201
-26
lines changed

board.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ type (
8383
Type string `json:"type"`
8484
Auto bool `json:"auto,omitempty"`
8585
AutoCount *int `json:"auto_count,omitempty"`
86-
Datasource *string `json:"datasource"`
86+
Datasource interface{} `json:"datasource"`
8787
Refresh BoolInt `json:"refresh"`
8888
Options []Option `json:"options"`
8989
IncludeAll bool `json:"includeAll"`
@@ -111,23 +111,23 @@ type (
111111
Value interface{} `json:"value"` // TODO select more precise type
112112
}
113113
Annotation struct {
114-
Name string `json:"name"`
115-
Datasource *string `json:"datasource"`
116-
ShowLine bool `json:"showLine"`
117-
IconColor string `json:"iconColor"`
118-
LineColor string `json:"lineColor"`
119-
IconSize uint `json:"iconSize"`
120-
Enable bool `json:"enable"`
121-
Query string `json:"query"`
122-
Expr string `json:"expr"`
123-
Step string `json:"step"`
124-
TextField string `json:"textField"`
125-
TextFormat string `json:"textFormat"`
126-
TitleFormat string `json:"titleFormat"`
127-
TagsField string `json:"tagsField"`
128-
Tags []string `json:"tags"`
129-
TagKeys string `json:"tagKeys"`
130-
Type string `json:"type"`
114+
Name string `json:"name"`
115+
Datasource interface{} `json:"datasource"`
116+
ShowLine bool `json:"showLine"`
117+
IconColor string `json:"iconColor"`
118+
LineColor string `json:"lineColor"`
119+
IconSize uint `json:"iconSize"`
120+
Enable bool `json:"enable"`
121+
Query string `json:"query"`
122+
Expr string `json:"expr"`
123+
Step string `json:"step"`
124+
TextField string `json:"textField"`
125+
TextFormat string `json:"textFormat"`
126+
TitleFormat string `json:"titleFormat"`
127+
TagsField string `json:"tagsField"`
128+
Tags []string `json:"tags"`
129+
TagKeys string `json:"tagKeys"`
130+
Type string `json:"type"`
131131
}
132132
// Link represents link to another dashboard or external weblink
133133
Link struct {

dashboard-unmarshal_test.go

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ func TestUnmarshal_DashboardWithGraphWithTargets26(t *testing.T) {
101101
if panel.OfType != sdk.GraphType {
102102
t.Errorf("panel type should be %d (\"graph\") type but got %d", sdk.GraphType, panel.OfType)
103103
}
104-
if *panel.Datasource != sdk.MixedSource {
105-
t.Errorf("panel Datasource should be \"%s\" but got \"%s\"", sdk.MixedSource, *panel.Datasource)
104+
if panel.Datasource != sdk.MixedSource {
105+
t.Errorf("panel Datasource should be \"%s\" but got \"%s\"", sdk.MixedSource, panel.Datasource)
106106
}
107107
if len(panel.GraphPanel.Targets) != 2 {
108108
t.Errorf("panel has 2 targets but got %d", len(panel.GraphPanel.Targets))
@@ -188,3 +188,40 @@ func TestUnmarshal_DashboardWithMixedYaxes(t *testing.T) {
188188
t.Errorf("panel #1 has wrong max value: %f, expected: %f", max4.Value, 100.0)
189189
}
190190
}
191+
192+
func TestUnmarshal_DashboardWithGraphWithTargets83(t *testing.T) {
193+
var board sdk.Board
194+
raw, _ := ioutil.ReadFile("testdata/default-panels-graph-with-target-8.3.json")
195+
196+
err := json.Unmarshal(raw, &board)
197+
198+
if err != nil {
199+
t.Fatal(err)
200+
}
201+
if len(board.Panels) != 2 {
202+
t.Fatalf("board should have 2 panels but got %d", len(board.Panels))
203+
}
204+
rowPanel := board.Panels[0]
205+
if rowPanel.OfType != sdk.RowType {
206+
t.Errorf("panel type should be %d (\"row\") type but got %d", sdk.GraphType, rowPanel.OfType)
207+
}
208+
209+
panel := board.Panels[1]
210+
if panel.OfType != sdk.GraphType {
211+
t.Errorf("panel type should be %d (\"graph\") type but got %d", sdk.GraphType, panel.OfType)
212+
}
213+
214+
if len(panel.GraphPanel.Targets) != 1 {
215+
t.Errorf("panel has 1 targets but got %d", len(panel.GraphPanel.Targets))
216+
}
217+
218+
target := panel.GraphPanel.Targets[0]
219+
datasource, ok := target.Datasource.(map[string]interface{})
220+
if !ok {
221+
t.Fatalf("target Datasource should be a map but got %T", panel.Datasource)
222+
}
223+
if datasource["type"] != "prometheus" {
224+
t.Errorf("target datasource should be of type \"prometheus\" but got %s", datasource["type"])
225+
}
226+
227+
}

panel.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ type (
6767
}
6868
panelType int8
6969
CommonPanel struct {
70-
Datasource *string `json:"datasource,omitempty"` // metrics
71-
Editable bool `json:"editable"`
72-
Error bool `json:"error"`
70+
Datasource interface{} `json:"datasource,omitempty"` // metrics
71+
Editable bool `json:"editable"`
72+
Error bool `json:"error"`
7373
GridPos struct {
7474
H *int `json:"h,omitempty"`
7575
W *int `json:"w,omitempty"`
@@ -550,9 +550,9 @@ type (
550550

551551
// for an any panel
552552
type Target struct {
553-
RefID string `json:"refId"`
554-
Datasource string `json:"datasource,omitempty"`
555-
Hide bool `json:"hide,omitempty"`
553+
RefID string `json:"refId"`
554+
Datasource interface{} `json:"datasource,omitempty"`
555+
Hide bool `json:"hide,omitempty"`
556556

557557
// For PostgreSQL
558558
Table string `json:"table,omitempty"`
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
{
2+
"annotations": {
3+
"list": [
4+
{
5+
"builtIn": 1,
6+
"datasource": "-- Grafana --",
7+
"enable": true,
8+
"hide": true,
9+
"iconColor": "rgba(0, 211, 255, 1)",
10+
"name": "Annotations & Alerts",
11+
"target": {
12+
"limit": 100,
13+
"matchAny": false,
14+
"tags": [],
15+
"type": "dashboard"
16+
},
17+
"type": "dashboard"
18+
}
19+
]
20+
},
21+
"editable": true,
22+
"fiscalYearStartMonth": 0,
23+
"graphTooltip": 0,
24+
"id": 12,
25+
"links": [],
26+
"liveNow": false,
27+
"panels": [
28+
{
29+
"gridPos": {
30+
"h": 1,
31+
"w": 24,
32+
"x": 0,
33+
"y": 0
34+
},
35+
"id": 4,
36+
"title": "Basic Row",
37+
"type": "row"
38+
},
39+
{
40+
"aliasColors": {},
41+
"bars": false,
42+
"dashLength": 10,
43+
"dashes": false,
44+
"fill": 1,
45+
"fillGradient": 0,
46+
"gridPos": {
47+
"h": 9,
48+
"w": 12,
49+
"x": 0,
50+
"y": 1
51+
},
52+
"hiddenSeries": false,
53+
"id": 2,
54+
"legend": {
55+
"avg": false,
56+
"current": false,
57+
"max": false,
58+
"min": false,
59+
"show": true,
60+
"total": false,
61+
"values": false
62+
},
63+
"lines": true,
64+
"linewidth": 1,
65+
"nullPointMode": "null",
66+
"options": {
67+
"alertThreshold": true
68+
},
69+
"percentage": false,
70+
"pluginVersion": "8.3.2",
71+
"pointradius": 2,
72+
"points": false,
73+
"renderer": "flot",
74+
"seriesOverrides": [],
75+
"spaceLength": 10,
76+
"stack": false,
77+
"steppedLine": false,
78+
"targets": [
79+
{
80+
"datasource": {
81+
"type": "prometheus",
82+
"uid": "Ilg0cn17k"
83+
},
84+
"exemplar": true,
85+
"expr": "go_goroutines{job=\"prometheus\"}",
86+
"interval": "",
87+
"legendFormat": "",
88+
"refId": "A"
89+
}
90+
],
91+
"thresholds": [],
92+
"timeRegions": [],
93+
"title": "Panel Title",
94+
"tooltip": {
95+
"shared": true,
96+
"sort": 0,
97+
"value_type": "individual"
98+
},
99+
"type": "graph",
100+
"xaxis": {
101+
"mode": "time",
102+
"show": true,
103+
"values": []
104+
},
105+
"yaxes": [
106+
{
107+
"format": "short",
108+
"logBase": 1,
109+
"show": true
110+
},
111+
{
112+
"format": "short",
113+
"logBase": 1,
114+
"show": true
115+
}
116+
],
117+
"yaxis": {
118+
"align": false
119+
}
120+
}
121+
],
122+
"schemaVersion": 33,
123+
"style": "dark",
124+
"tags": [],
125+
"templating": {
126+
"list": []
127+
},
128+
"time": {
129+
"from": "now-6h",
130+
"to": "now"
131+
},
132+
"timepicker": {},
133+
"timezone": "",
134+
"title": "Basic Dashboard",
135+
"uid": "t5LxFe17z",
136+
"version": 4,
137+
"weekStart": ""
138+
}

0 commit comments

Comments
 (0)