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

Commit d1db715

Browse files
committed
datasource: add support for HTTP headers
Signed-off-by: Guillaume Delbergue <[email protected]>
1 parent 3049c69 commit d1db715

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

datasource.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ package gapi
33
import (
44
"bytes"
55
"encoding/json"
6+
"errors"
67
"fmt"
8+
"regexp"
9+
"strconv"
710
)
811

912
// DataSource represents a Grafana data source.
@@ -27,16 +30,52 @@ type DataSource struct {
2730
// Deprecated: Use secureJsonData.basicAuthPassword instead.
2831
BasicAuthPassword string `json:"basicAuthPassword,omitempty"`
2932

33+
// Helper to read/write http headers
34+
HTTPHeaders map[string]string `json:"-"`
35+
3036
JSONData JSONData `json:"jsonData,omitempty"`
3137
SecureJSONData SecureJSONData `json:"secureJsonData,omitempty"`
3238
}
3339

40+
// Required to avoid recursion during (un)marshal
41+
type _DataSource DataSource
42+
43+
// Marshal DataSource
44+
func (ds *DataSource) MarshalJSON() ([]byte, error) {
45+
var index int64
46+
dataSource := _DataSource(*ds)
47+
dataSource.JSONData.httpHeaderNames = make(map[int64]string, len(ds.HTTPHeaders))
48+
dataSource.SecureJSONData.httpHeaderValues = make(map[int64]string, len(ds.HTTPHeaders))
49+
for name, value := range ds.HTTPHeaders {
50+
dataSource.JSONData.httpHeaderNames[index] = name
51+
dataSource.SecureJSONData.httpHeaderValues[index] = value
52+
index++
53+
}
54+
return json.Marshal(dataSource)
55+
}
56+
57+
// Unmarshal DataSource
58+
func (ds *DataSource) UnmarshalJSON(b []byte) (err error) {
59+
dataSource := _DataSource(*ds)
60+
if err = json.Unmarshal(b, &dataSource); err == nil {
61+
*ds = DataSource(dataSource)
62+
}
63+
if len(ds.JSONData.httpHeaderNames) != len(ds.SecureJSONData.httpHeaderValues) {
64+
return errors.New("HTTP headers names length doesn't match HTTP header values length")
65+
}
66+
for index, value := range ds.JSONData.httpHeaderNames {
67+
ds.HTTPHeaders[value] = ds.SecureJSONData.httpHeaderValues[index]
68+
}
69+
return err
70+
}
71+
3472
// JSONData is a representation of the datasource `jsonData` property
3573
type JSONData struct {
3674
// Used by all datasources
3775
TLSAuth bool `json:"tlsAuth,omitempty"`
3876
TLSAuthWithCACert bool `json:"tlsAuthWithCACert,omitempty"`
3977
TLSSkipVerify bool `json:"tlsSkipVerify,omitempty"`
78+
httpHeaderNames map[int64]string
4079

4180
// Used by Graphite
4281
GraphiteVersion string `json:"graphiteVersion,omitempty"`
@@ -95,6 +134,49 @@ type JSONData struct {
95134
SigV4Region string `json:"sigV4Region,omitempty"`
96135
}
97136

137+
// Required to avoid recursion during (un)marshal
138+
type _JSONData JSONData
139+
140+
// Marshal JSONData
141+
func (jd JSONData) MarshalJSON() ([]byte, error) {
142+
jsonData := _JSONData(jd)
143+
b, err := json.Marshal(jsonData)
144+
if err != nil {
145+
return nil, err
146+
}
147+
fields := make(map[string]interface{})
148+
if err = json.Unmarshal(b, &fields); err != nil {
149+
return nil, err
150+
}
151+
for index, name := range jd.httpHeaderNames {
152+
fields[fmt.Sprintf("httpHeaderName%d", index+1)] = name
153+
}
154+
return json.Marshal(fields)
155+
}
156+
157+
// Unmarshal JSONData
158+
func (jd *JSONData) UnmarshalJSON(b []byte) (err error) {
159+
jsonData := _JSONData(*jd)
160+
if err = json.Unmarshal(b, &jsonData); err == nil {
161+
*jd = JSONData(jsonData)
162+
}
163+
fields := make(map[string]interface{})
164+
if err = json.Unmarshal(b, &fields); err == nil {
165+
for name, value := range fields {
166+
re := regexp.MustCompile("httpHeaderName([0-9]+)")
167+
match := re.FindStringSubmatch(name)
168+
if len(match) == 1 {
169+
index, err := strconv.ParseInt(match[0], 10, 64)
170+
if err != nil {
171+
return err
172+
}
173+
jd.httpHeaderNames[index-1] = value.(string)
174+
}
175+
}
176+
}
177+
return err
178+
}
179+
98180
// SecureJSONData is a representation of the datasource `secureJsonData` property
99181
type SecureJSONData struct {
100182
// Used by all datasources
@@ -103,6 +185,7 @@ type SecureJSONData struct {
103185
TLSClientKey string `json:"tlsClientKey,omitempty"`
104186
Password string `json:"password,omitempty"`
105187
BasicAuthPassword string `json:"basicAuthPassword,omitempty"`
188+
httpHeaderValues map[int64]string
106189

107190
// Used by Cloudwatch
108191
AccessKey string `json:"accessKey,omitempty"`
@@ -116,6 +199,26 @@ type SecureJSONData struct {
116199
SigV4SecretKey string `json:"sigV4SecretKey,omitempty"`
117200
}
118201

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

0 commit comments

Comments
 (0)