Skip to content

Commit 825cd34

Browse files
authored
Add health check for async queries (#124)
Add health check for async queries
1 parent ba2e2a8 commit 825cd34

File tree

4 files changed

+116
-0
lines changed

4 files changed

+116
-0
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ require (
7575
github.com/prometheus/common v0.46.0 // indirect
7676
github.com/prometheus/procfs v0.12.0 // indirect
7777
github.com/russross/blackfriday/v2 v2.1.0 // indirect
78+
github.com/stretchr/objx v0.5.0 // indirect
7879
github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8 // indirect
7980
github.com/unknwon/com v1.0.1 // indirect
8081
github.com/unknwon/log v0.0.0-20150304194804-e617c87089d3 // indirect

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:X
227227
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
228228
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
229229
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
230+
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
230231
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
231232
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
232233
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=

pkg/awsds/asyncDatasource.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,29 @@ func (ds *AsyncAWSDatasource) QueryData(ctx context.Context, req *backend.QueryD
130130
return response.Response(), nil
131131
}
132132

133+
func (ds *AsyncAWSDatasource) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
134+
datasourceUID := req.PluginContext.DataSourceInstanceSettings.UID
135+
key := defaultKey(datasourceUID)
136+
dbConn, ok := ds.getDBConnection(key)
137+
if !ok {
138+
return &backend.CheckHealthResult{
139+
Status: backend.HealthStatusError,
140+
Message: "No database connection found for datasource uid: " + datasourceUID,
141+
}, nil
142+
}
143+
err := dbConn.db.Ping(ctx)
144+
if err != nil {
145+
return &backend.CheckHealthResult{
146+
Status: backend.HealthStatusError,
147+
Message: err.Error(),
148+
}, nil
149+
}
150+
return &backend.CheckHealthResult{
151+
Status: backend.HealthStatusOk,
152+
Message: "Data source is working",
153+
}, nil
154+
}
155+
133156
func (ds *AsyncAWSDatasource) getAsyncDBFromQuery(q *AsyncQuery, datasourceUID string) (AsyncDB, error) {
134157
if !ds.EnableMultipleConnections && len(q.ConnectionArgs) > 0 {
135158
return nil, sqlds.ErrorMissingMultipleConnectionsConfig

pkg/awsds/asyncDatasource_test.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ import (
44
"context"
55
"database/sql/driver"
66
"encoding/json"
7+
"fmt"
8+
"sync"
79
"testing"
810

911
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
1012

1113
"github.com/grafana/grafana-plugin-sdk-go/backend"
1214
"github.com/grafana/sqlds/v3"
1315
"github.com/stretchr/testify/assert"
16+
"github.com/stretchr/testify/mock"
1417
)
1518

1619
type fakeAsyncDB struct{}
@@ -136,3 +139,91 @@ func Test_Async_QueryData_uses_synchronous_flow_when_header_has_alert_and_expres
136139
})
137140
}
138141
}
142+
143+
type MockDB struct {
144+
mock.Mock
145+
}
146+
147+
func (m *MockDB) Ping(context context.Context) error {
148+
args := m.Called(context)
149+
return args.Error(0)
150+
}
151+
152+
func (m *MockDB) Begin() (driver.Tx, error) {
153+
args := m.Called()
154+
return args.Get(0).(driver.Tx), args.Error(1)
155+
}
156+
157+
func (m *MockDB) CancelQuery(ctx context.Context, queryID string) error {
158+
args := m.Called(ctx, queryID)
159+
return args.Error(0)
160+
}
161+
func (m *MockDB) Close() error {
162+
args := m.Called()
163+
return args.Error(0)
164+
}
165+
func (m *MockDB) GetQueryID(ctx context.Context, query string, args ...interface{}) (bool, string, error) {
166+
arg := m.Called(ctx, query, args)
167+
return arg.Bool(0), arg.String(1), arg.Error(2)
168+
}
169+
func (m *MockDB) GetRows(ctx context.Context, queryID string) (driver.Rows, error) {
170+
args := m.Called(ctx, queryID)
171+
return args.Get(0).(driver.Rows), args.Error(1)
172+
}
173+
func (m *MockDB) Prepare(query string) (driver.Stmt, error) {
174+
args := m.Called(query)
175+
return args.Get(0).(driver.Stmt), args.Error(1)
176+
}
177+
func (m *MockDB) QueryStatus(ctx context.Context, queryID string) (QueryStatus, error) {
178+
args := m.Called(ctx, queryID)
179+
return args.Get(0).(QueryStatus), args.Error(1)
180+
}
181+
func (m *MockDB) StartQuery(ctx context.Context, query string, args ...interface{}) (string, error) {
182+
arg := m.Called(ctx, query, args)
183+
return arg.String(0), arg.Error(1)
184+
}
185+
186+
func Test_AsyncDatasource_CheckHealth(t *testing.T) {
187+
tests := []struct {
188+
desc string
189+
mockPingResponse error
190+
expected *backend.CheckHealthResult
191+
}{
192+
{
193+
desc: "it returns an error when ping fails",
194+
mockPingResponse: fmt.Errorf("your auth wasn't right"),
195+
expected: &backend.CheckHealthResult{
196+
Status: backend.HealthStatusError,
197+
Message: "your auth wasn't right",
198+
},
199+
},
200+
{
201+
desc: "it returns an ok when the query succeeds",
202+
mockPingResponse: nil,
203+
expected: &backend.CheckHealthResult{
204+
Status: backend.HealthStatusOk,
205+
Message: "Data source is working",
206+
},
207+
},
208+
}
209+
for _, tt := range tests {
210+
t.Run(tt.desc, func(t *testing.T) {
211+
db := new(MockDB)
212+
db.On("Ping", context.Background()).Return(tt.mockPingResponse)
213+
dbC := dbConnection{
214+
db,
215+
backend.DataSourceInstanceSettings{UID: "uid1"},
216+
}
217+
ds := &AsyncAWSDatasource{dbConnections: sync.Map{}}
218+
ds.dbConnections.Store(defaultKey("uid1"), dbC)
219+
220+
result, err := ds.CheckHealth(context.Background(), &backend.CheckHealthRequest{
221+
PluginContext: backend.PluginContext{
222+
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{UID: "uid1"},
223+
},
224+
})
225+
assert.NoError(t, err)
226+
assert.Equal(t, tt.expected, result)
227+
})
228+
}
229+
}

0 commit comments

Comments
 (0)