@@ -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.
1014type 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
3669type 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,14 +131,66 @@ 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
101186type SecureJSONData struct {
102187 // Used by all datasources
103188 TLSCACert string `json:"tlsCACert,omitempty"`
104189 TLSClientCert string `json:"tlsClientCert,omitempty"`
105190 TLSClientKey string `json:"tlsClientKey,omitempty"`
106191 Password string `json:"password,omitempty"`
107- BasicAuthPassword string `json:"basicAuthPassword,omitempty"`
192+ BasicAuthPassword string `json:"basicAuthPassword,om itempty"`
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.
122228func (c * Client ) NewDataSource (s * DataSource ) (int64 , error ) {
123229 data , err := json .Marshal (s )
0 commit comments