@@ -4,11 +4,16 @@ 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"`
16+ UID string `json:"uid,omitempty"`
1217 Name string `json:"name"`
1318 Type string `json:"type"`
1419 URL string `json:"url"`
@@ -27,16 +32,46 @@ type DataSource struct {
2732 // Deprecated: Use secureJsonData.basicAuthPassword instead.
2833 BasicAuthPassword string `json:"basicAuthPassword,omitempty"`
2934
35+ // Helper to read/write http headers
36+ HTTPHeaders map [string ]string `json:"-"`
37+
3038 JSONData JSONData `json:"jsonData,omitempty"`
3139 SecureJSONData SecureJSONData `json:"secureJsonData,omitempty"`
3240}
3341
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+
3468// JSONData is a representation of the datasource `jsonData` property
3569type JSONData struct {
3670 // Used by all datasources
3771 TLSAuth bool `json:"tlsAuth,omitempty"`
3872 TLSAuthWithCACert bool `json:"tlsAuthWithCACert,omitempty"`
3973 TLSSkipVerify bool `json:"tlsSkipVerify,omitempty"`
74+ httpHeaderNames []string
4075
4176 // Used by Graphite
4277 GraphiteVersion string `json:"graphiteVersion,omitempty"`
@@ -94,6 +129,64 @@ type JSONData struct {
94129 SigV4ExternalID string `json:"sigV4ExternalID,omitempty"`
95130 SigV4Profile string `json:"sigV4Profile,omitempty"`
96131 SigV4Region string `json:"sigV4Region,omitempty"`
132+
133+ // Used by Prometheus and Loki
134+ ManageAlerts bool `json:"manageAlerts,omitempty"`
135+ AlertmanagerUID string `json:"alertmanagerUid,omitempty"`
136+
137+ // Used by Alertmanager
138+ Implementation string `json:"implementation,omitempty"`
139+ }
140+
141+ // Required to avoid recursion during (un)marshal
142+ type _JSONData JSONData
143+
144+ // Marshal JSONData
145+ func (jd JSONData ) MarshalJSON () ([]byte , error ) {
146+ jsonData := _JSONData (jd )
147+ b , err := json .Marshal (jsonData )
148+ if err != nil {
149+ return nil , err
150+ }
151+ fields := make (map [string ]interface {})
152+ if err = json .Unmarshal (b , & fields ); err != nil {
153+ return nil , err
154+ }
155+ for index , name := range jd .httpHeaderNames {
156+ fields [fmt .Sprintf ("httpHeaderName%d" , index + 1 )] = name
157+ }
158+ return json .Marshal (fields )
159+ }
160+
161+ // Unmarshal JSONData
162+ func (jd * JSONData ) UnmarshalJSON (b []byte ) (err error ) {
163+ jsonData := _JSONData (* jd )
164+ if err = json .Unmarshal (b , & jsonData ); err == nil {
165+ * jd = JSONData (jsonData )
166+ }
167+ fields := make (map [string ]interface {})
168+ if err = json .Unmarshal (b , & fields ); err == nil {
169+ headerCount := 0
170+ for name := range fields {
171+ match := headerNameRegex .FindStringSubmatch (name )
172+ if len (match ) > 0 {
173+ headerCount ++
174+ }
175+ }
176+
177+ jd .httpHeaderNames = make ([]string , headerCount )
178+ for name , value := range fields {
179+ match := headerNameRegex .FindStringSubmatch (name )
180+ if len (match ) == 2 {
181+ index , err := strconv .ParseInt (match [1 ], 10 , 64 )
182+ if err != nil {
183+ return err
184+ }
185+ jd .httpHeaderNames [index - 1 ] = value .(string )
186+ }
187+ }
188+ }
189+ return err
97190}
98191
99192// SecureJSONData is a representation of the datasource `secureJsonData` property
@@ -104,6 +197,7 @@ type SecureJSONData struct {
104197 TLSClientKey string `json:"tlsClientKey,omitempty"`
105198 Password string `json:"password,omitempty"`
106199 BasicAuthPassword string `json:"basicAuthPassword,omitempty"`
200+ httpHeaderValues []string
107201
108202 // Used by Cloudwatch
109203 AccessKey string `json:"accessKey,omitempty"`
@@ -117,6 +211,26 @@ type SecureJSONData struct {
117211 SigV4SecretKey string `json:"sigV4SecretKey,omitempty"`
118212}
119213
214+ // Required to avoid recursion during unmarshal
215+ type _SecureJSONData SecureJSONData
216+
217+ // Marshal SecureJSONData
218+ func (sjd SecureJSONData ) MarshalJSON () ([]byte , error ) {
219+ secureJSONData := _SecureJSONData (sjd )
220+ b , err := json .Marshal (secureJSONData )
221+ if err != nil {
222+ return nil , err
223+ }
224+ fields := make (map [string ]interface {})
225+ if err = json .Unmarshal (b , & fields ); err != nil {
226+ return nil , err
227+ }
228+ for index , value := range sjd .httpHeaderValues {
229+ fields [fmt .Sprintf ("httpHeaderValue%d" , index + 1 )] = value
230+ }
231+ return json .Marshal (fields )
232+ }
233+
120234// NewDataSource creates a new Grafana data source.
121235func (c * Client ) NewDataSource (s * DataSource ) (int64 , error ) {
122236 data , err := json .Marshal (s )
0 commit comments