@@ -18,13 +18,13 @@ import (
18
18
)
19
19
20
20
type fakeDriver struct {
21
- openDBfn func () (* sql.DB , error )
21
+ openDBfn func (msg json. RawMessage ) (* sql.DB , error )
22
22
23
23
Driver
24
24
}
25
25
26
- func (d fakeDriver ) Connect (backend.DataSourceInstanceSettings , json.RawMessage ) (db * sql.DB , err error ) {
27
- return d .openDBfn ()
26
+ func (d fakeDriver ) Connect (settings backend.DataSourceInstanceSettings , msg json.RawMessage ) (db * sql.DB , err error ) {
27
+ return d .openDBfn (msg )
28
28
}
29
29
30
30
func (d fakeDriver ) Macros () Macros {
@@ -35,13 +35,11 @@ func (d fakeDriver) Converters() []sqlutil.Converter {
35
35
return []sqlutil.Converter {}
36
36
}
37
37
38
- // func (d fakeDriver) Settings(backend.DataSourceInstanceSettings) DriverSettings
39
-
40
38
func Test_getDBConnectionFromQuery (t * testing.T ) {
41
39
db := & sql.DB {}
42
40
db2 := & sql.DB {}
43
41
db3 := & sql.DB {}
44
- d := & fakeDriver {openDBfn : func () (* sql.DB , error ) { return db3 , nil }}
42
+ d := & fakeDriver {openDBfn : func (msg json. RawMessage ) (* sql.DB , error ) { return db3 , nil }}
45
43
tests := []struct {
46
44
desc string
47
45
dsUID string
@@ -136,15 +134,21 @@ func Test_timeout_retries(t *testing.T) {
136
134
dsUID := "timeout"
137
135
settings := backend.DataSourceInstanceSettings {UID : dsUID }
138
136
139
- handler := testSqlHandler {}
137
+ handler := & testSqlHandler {}
140
138
mockDriver := "sqlmock"
141
139
mock .RegisterDriver (mockDriver , handler )
142
140
db , err := sql .Open (mockDriver , "" )
143
141
if err != nil {
144
142
t .Errorf ("failed to connect to mock driver: %v" , err )
145
143
}
146
144
timeoutDriver := fakeDriver {
147
- openDBfn : func () (* sql.DB , error ) { return db , nil },
145
+ openDBfn : func (msg json.RawMessage ) (* sql.DB , error ) {
146
+ db , err := sql .Open (mockDriver , "" )
147
+ if err != nil {
148
+ t .Errorf ("failed to connect to mock driver: %v" , err )
149
+ }
150
+ return db , nil
151
+ },
148
152
}
149
153
retries := 5
150
154
max := time .Duration (testTimeout ) * time .Second
@@ -173,14 +177,14 @@ func Test_error_retries(t *testing.T) {
173
177
dsUID := "error"
174
178
settings := backend.DataSourceInstanceSettings {UID : dsUID }
175
179
176
- handler := testSqlHandler {
180
+ handler := & testSqlHandler {
177
181
error : errors .New ("foo" ),
178
182
}
179
183
mockDriver := "sqlmock-error"
180
184
mock .RegisterDriver (mockDriver , handler )
181
185
182
186
timeoutDriver := fakeDriver {
183
- openDBfn : func () (* sql.DB , error ) {
187
+ openDBfn : func (msg json. RawMessage ) (* sql.DB , error ) {
184
188
db , err := sql .Open (mockDriver , "" )
185
189
if err != nil {
186
190
t .Errorf ("failed to connect to mock driver: %v" , err )
@@ -220,19 +224,154 @@ func Test_error_retries(t *testing.T) {
220
224
221
225
}
222
226
227
+ func Test_query_apply_headers (t * testing.T ) {
228
+ testCounter = 0
229
+ dsUID := "headers"
230
+ settings := backend.DataSourceInstanceSettings {UID : dsUID }
231
+
232
+ // first query will fail since the connection is missing tokens
233
+ handler := & testSqlHandler {
234
+ error : errors .New ("missing token" ),
235
+ }
236
+ mockDriver := "sqlmock-query-error"
237
+ mock .RegisterDriver (mockDriver , handler )
238
+
239
+ opened := false
240
+ var message json.RawMessage
241
+ timeoutDriver := fakeDriver {
242
+ openDBfn : func (msg json.RawMessage ) (* sql.DB , error ) {
243
+ if opened {
244
+ // second query attempt will have tokens and won't return an error
245
+ handler = & testSqlHandler {}
246
+ mockDriver = "sqlmock-query-token"
247
+ mock .RegisterDriver (mockDriver , handler )
248
+ }
249
+ db , err := sql .Open (mockDriver , "" )
250
+ if err != nil {
251
+ t .Errorf ("failed to connect to mock driver: %v" , err )
252
+ }
253
+ opened = true
254
+ message = msg
255
+ return db , nil
256
+ },
257
+ }
258
+ max := time .Duration (10 ) * time .Second
259
+ // retry once for token errors since the first connection will not have the token and throw a connection error
260
+ driverSettings := DriverSettings {Retries : 1 , Timeout : max , Pause : 1 , RetryOn : []string {"token" }, ForwardHeaders : true }
261
+ ds := & SQLDatasource {c : timeoutDriver , driverSettings : driverSettings }
262
+
263
+ key := defaultKey (dsUID )
264
+ // Add the mandatory default db
265
+ db , _ := timeoutDriver .Connect (settings , nil )
266
+ ds .storeDBConnection (key , dbConnection {db , settings })
267
+ ctx := context .Background ()
268
+
269
+ qry := `{ "rawSql": "foo" }`
270
+
271
+ req := & backend.QueryDataRequest {
272
+ PluginContext : backend.PluginContext {
273
+ DataSourceInstanceSettings : & settings ,
274
+ },
275
+ Queries : []backend.DataQuery {
276
+ {
277
+ RefID : "foo" ,
278
+ JSON : []byte (qry ),
279
+ },
280
+ },
281
+ }
282
+ req .SetHTTPHeader ("hey" , "scott" )
283
+
284
+ data , err := ds .QueryData (ctx , req )
285
+ assert .Nil (t , err )
286
+ assert .NotNil (t , data .Responses )
287
+
288
+ res := data .Responses ["foo" ]
289
+ assert .Nil (t , res .Error )
290
+
291
+ assert .Contains (t , string (message ), "scott" )
292
+ }
293
+
294
+ func Test_check_health_with_headers (t * testing.T ) {
295
+ dsUID := "headers"
296
+ settings := backend.DataSourceInstanceSettings {UID : dsUID }
297
+
298
+ // first check will fail since the connection is missing tokens
299
+ handler := & testSqlHandler {
300
+ error : errors .New ("missing token" ),
301
+ }
302
+ mockDriver := "sqlmock-header-error"
303
+ mock .RegisterDriver (mockDriver , handler )
304
+
305
+ opened := false
306
+ var message json.RawMessage
307
+ timeoutDriver := fakeDriver {
308
+ openDBfn : func (msg json.RawMessage ) (* sql.DB , error ) {
309
+ if opened {
310
+ // second query attempt will have tokens and won't return an error
311
+ handler = & testSqlHandler {
312
+ ping : true ,
313
+ checks : handler .checks ,
314
+ }
315
+ mockDriver = "sqlmock-header-token"
316
+ mock .RegisterDriver (mockDriver , handler )
317
+ }
318
+ db , err := sql .Open (mockDriver , "" )
319
+ if err != nil {
320
+ t .Errorf ("failed to connect to mock driver: %v" , err )
321
+ }
322
+ opened = true
323
+ message = msg
324
+ return db , nil
325
+ },
326
+ }
327
+ max := time .Duration (10 ) * time .Second
328
+ // retry once for token errors since the first connection will not have the token and throw a connection error
329
+ driverSettings := DriverSettings {Retries : 1 , Timeout : max , Pause : 1 , RetryOn : []string {"token" }, ForwardHeaders : true }
330
+ ds := & SQLDatasource {c : timeoutDriver , driverSettings : driverSettings }
331
+
332
+ key := defaultKey (dsUID )
333
+ // Add the mandatory default db
334
+ db , _ := timeoutDriver .Connect (settings , nil )
335
+ ds .storeDBConnection (key , dbConnection {db , settings })
336
+ ctx := context .Background ()
337
+
338
+ headers := map [string ]string {}
339
+ headers ["foo" ] = "bar"
340
+ req := & backend.CheckHealthRequest {
341
+ PluginContext : backend.PluginContext {
342
+ DataSourceInstanceSettings : & settings ,
343
+ },
344
+ Headers : headers ,
345
+ }
346
+
347
+ req .SetHTTPHeader ("foo" , "bar" )
348
+
349
+ res , err := ds .CheckHealth (ctx , req )
350
+ assert .Nil (t , err )
351
+ assert .Equal (t , "Data source is working" , res .Message )
352
+
353
+ assert .Contains (t , string (message ), "bar" )
354
+ }
355
+
223
356
var testCounter = 0
224
357
var testTimeout = 1
225
358
var testRows = 0
226
359
227
360
type testSqlHandler struct {
228
361
mock.DBHandler
229
362
error
363
+ ping bool
364
+ checks int
230
365
}
231
366
232
- func (s testSqlHandler ) Ping (ctx context.Context ) error {
367
+ func (s * testSqlHandler ) Ping (ctx context.Context ) error {
368
+ s .checks += 1
233
369
if s .error != nil {
234
370
return s .error
235
371
}
372
+ if s .ping {
373
+ return nil
374
+ }
236
375
testCounter ++ // track the retries for the test assertion
237
376
time .Sleep (time .Duration (testTimeout + 1 )) // simulate a connection delay
238
377
select {
@@ -242,7 +381,7 @@ func (s testSqlHandler) Ping(ctx context.Context) error {
242
381
}
243
382
}
244
383
245
- func (s testSqlHandler ) Query (args []driver.Value ) (driver.Rows , error ) {
384
+ func (s * testSqlHandler ) Query (args []driver.Value ) (driver.Rows , error ) {
246
385
fmt .Println ("query" )
247
386
if s .error != nil {
248
387
testCounter ++
@@ -251,11 +390,11 @@ func (s testSqlHandler) Query(args []driver.Value) (driver.Rows, error) {
251
390
return s , nil
252
391
}
253
392
254
- func (s testSqlHandler ) Columns () []string {
393
+ func (s * testSqlHandler ) Columns () []string {
255
394
return []string {"foo" , "bar" }
256
395
}
257
396
258
- func (s testSqlHandler ) Next (dest []driver.Value ) error {
397
+ func (s * testSqlHandler ) Next (dest []driver.Value ) error {
259
398
testRows ++
260
399
if testRows > 5 {
261
400
return io .EOF
@@ -265,6 +404,6 @@ func (s testSqlHandler) Next(dest []driver.Value) error {
265
404
return nil
266
405
}
267
406
268
- func (s testSqlHandler ) Close () error {
407
+ func (s * testSqlHandler ) Close () error {
269
408
return nil
270
409
}
0 commit comments