Skip to content
This repository was archived by the owner on Jan 15, 2024. It is now read-only.

Commit a8d033c

Browse files
Merge pull request #33 from guyguy333/data-source-http-headers
Data source: add support for http headers
2 parents ff02ac6 + aae2f42 commit a8d033c

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

datasource.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@ import (
44
"bytes"
55
"encoding/json"
66
"fmt"
7+
"regexp"
8+
"strconv"
79
)
810

11+
var headerNameRegex = regexp.MustCompile(`^httpHeaderName(\d+)$`)
12+
913
// DataSource represents a Grafana data source.
1014
type DataSource struct {
1115
ID int64 `json:"id,omitempty"`
@@ -28,16 +32,46 @@ type DataSource struct {
2832
// Deprecated: Use secureJsonData.basicAuthPassword instead.
2933
BasicAuthPassword string `json:"basicAuthPassword,omitempty"`
3034

35+
// Helper to read/write http headers
36+
HTTPHeaders map[string]string `json:"-"`
37+
3138
JSONData JSONData `json:"jsonData,omitempty"`
3239
SecureJSONData SecureJSONData `json:"secureJsonData,omitempty"`
3340
}
3441

42+
// Required to avoid recursion during (un)marshal
43+
type _DataSource DataSource
44+
45+
// Marshal DataSource
46+
func (ds *DataSource) MarshalJSON() ([]byte, error) {
47+
dataSource := _DataSource(*ds)
48+
for name, value := range ds.HTTPHeaders {
49+
dataSource.JSONData.httpHeaderNames = append(dataSource.JSONData.httpHeaderNames, name)
50+
dataSource.SecureJSONData.httpHeaderValues = append(dataSource.SecureJSONData.httpHeaderValues, value)
51+
}
52+
return json.Marshal(dataSource)
53+
}
54+
55+
// Unmarshal DataSource
56+
func (ds *DataSource) UnmarshalJSON(b []byte) (err error) {
57+
dataSource := _DataSource(*ds)
58+
if err = json.Unmarshal(b, &dataSource); err == nil {
59+
*ds = DataSource(dataSource)
60+
}
61+
ds.HTTPHeaders = make(map[string]string)
62+
for _, value := range ds.JSONData.httpHeaderNames {
63+
ds.HTTPHeaders[value] = "true" // HTTP Headers are not returned by the API
64+
}
65+
return err
66+
}
67+
3568
// JSONData is a representation of the datasource `jsonData` property
3669
type JSONData struct {
3770
// Used by all datasources
3871
TLSAuth bool `json:"tlsAuth,omitempty"`
3972
TLSAuthWithCACert bool `json:"tlsAuthWithCACert,omitempty"`
4073
TLSSkipVerify bool `json:"tlsSkipVerify,omitempty"`
74+
httpHeaderNames []string
4175

4276
// Used by Graphite
4377
GraphiteVersion string `json:"graphiteVersion,omitempty"`
@@ -97,6 +131,57 @@ type JSONData struct {
97131
SigV4Region string `json:"sigV4Region,omitempty"`
98132
}
99133

134+
// Required to avoid recursion during (un)marshal
135+
type _JSONData JSONData
136+
137+
// Marshal JSONData
138+
func (jd JSONData) MarshalJSON() ([]byte, error) {
139+
jsonData := _JSONData(jd)
140+
b, err := json.Marshal(jsonData)
141+
if err != nil {
142+
return nil, err
143+
}
144+
fields := make(map[string]interface{})
145+
if err = json.Unmarshal(b, &fields); err != nil {
146+
return nil, err
147+
}
148+
for index, name := range jd.httpHeaderNames {
149+
fields[fmt.Sprintf("httpHeaderName%d", index+1)] = name
150+
}
151+
return json.Marshal(fields)
152+
}
153+
154+
// Unmarshal JSONData
155+
func (jd *JSONData) UnmarshalJSON(b []byte) (err error) {
156+
jsonData := _JSONData(*jd)
157+
if err = json.Unmarshal(b, &jsonData); err == nil {
158+
*jd = JSONData(jsonData)
159+
}
160+
fields := make(map[string]interface{})
161+
if err = json.Unmarshal(b, &fields); err == nil {
162+
headerCount := 0
163+
for name := range fields {
164+
match := headerNameRegex.FindStringSubmatch(name)
165+
if len(match) > 0 {
166+
headerCount++
167+
}
168+
}
169+
170+
jd.httpHeaderNames = make([]string, headerCount)
171+
for name, value := range fields {
172+
match := headerNameRegex.FindStringSubmatch(name)
173+
if len(match) == 2 {
174+
index, err := strconv.ParseInt(match[1], 10, 64)
175+
if err != nil {
176+
return err
177+
}
178+
jd.httpHeaderNames[index-1] = value.(string)
179+
}
180+
}
181+
}
182+
return err
183+
}
184+
100185
// SecureJSONData is a representation of the datasource `secureJsonData` property
101186
type SecureJSONData struct {
102187
// Used by all datasources
@@ -105,6 +190,7 @@ type SecureJSONData struct {
105190
TLSClientKey string `json:"tlsClientKey,omitempty"`
106191
Password string `json:"password,omitempty"`
107192
BasicAuthPassword string `json:"basicAuthPassword,omitempty"`
193+
httpHeaderValues []string
108194

109195
// Used by Cloudwatch
110196
AccessKey string `json:"accessKey,omitempty"`
@@ -118,6 +204,26 @@ type SecureJSONData struct {
118204
SigV4SecretKey string `json:"sigV4SecretKey,omitempty"`
119205
}
120206

207+
// Required to avoid recursion during unmarshal
208+
type _SecureJSONData SecureJSONData
209+
210+
// Marshal SecureJSONData
211+
func (sjd SecureJSONData) MarshalJSON() ([]byte, error) {
212+
secureJSONData := _SecureJSONData(sjd)
213+
b, err := json.Marshal(secureJSONData)
214+
if err != nil {
215+
return nil, err
216+
}
217+
fields := make(map[string]interface{})
218+
if err = json.Unmarshal(b, &fields); err != nil {
219+
return nil, err
220+
}
221+
for index, value := range sjd.httpHeaderValues {
222+
fields[fmt.Sprintf("httpHeaderValue%d", index+1)] = value
223+
}
224+
return json.Marshal(fields)
225+
}
226+
121227
// NewDataSource creates a new Grafana data source.
122228
func (c *Client) NewDataSource(s *DataSource) (int64, error) {
123229
data, err := json.Marshal(s)

0 commit comments

Comments
 (0)