k8s/query+ds: catch query errors, fix datasourceProvider and expose prometheus (#85071)

This commit is contained in:
Ryan McKinley 2024-03-25 17:22:34 +03:00 committed by GitHub
parent 2f3a01f79f
commit e6fa367d02
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 61 additions and 17 deletions

14
.vscode/launch.json vendored
View File

@ -23,6 +23,20 @@
"--secure-port=8443",
"--runtime-config=testdata.datasource.grafana.app/v0alpha1=true"]
},
{
"name": "Run API Server (query-localhost)",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/pkg/cmd/grafana/",
"env": {},
"cwd": "${workspaceFolder}",
"args": ["apiserver",
"--secure-port=8443",
"--runtime-config=query.grafana.app/v0alpha1=true",
"--hg-url=http://localhost:3000",
"--hg-key=$HGAPIKEY"]
},
{
"name": "Attach to Chrome",
"port": 9222,

View File

@ -31,6 +31,10 @@ type PluginDatasourceProvider interface {
GetInstanceSettings(ctx context.Context, uid string) (*backend.DataSourceInstanceSettings, error)
}
type ScopedPluginDatasourceProvider interface {
GetDatasourceProvider(pluginJson plugins.JSONData) PluginDatasourceProvider
}
// PluginContext requires adding system settings (feature flags, etc) to the datasource config
type PluginContextWrapper interface {
PluginContextForDataSource(ctx context.Context, datasourceSettings *backend.DataSourceInstanceSettings) (backend.PluginContext, error)
@ -39,18 +43,30 @@ type PluginContextWrapper interface {
func ProvideDefaultPluginConfigs(
dsService datasources.DataSourceService,
dsCache datasources.CacheService,
contextProvider *plugincontext.Provider) PluginDatasourceProvider {
return &defaultPluginDatasourceProvider{
plugin: plugins.JSONData{
ID: datasources.DS_TESTDATA,
},
contextProvider *plugincontext.Provider) ScopedPluginDatasourceProvider {
return &cachingDatasourceProvider{
dsService: dsService,
dsCache: dsCache,
contextProvider: contextProvider,
}
}
type defaultPluginDatasourceProvider struct {
type cachingDatasourceProvider struct {
dsService datasources.DataSourceService
dsCache datasources.CacheService
contextProvider *plugincontext.Provider
}
func (q *cachingDatasourceProvider) GetDatasourceProvider(pluginJson plugins.JSONData) PluginDatasourceProvider {
return &scopedDatasourceProvider{
plugin: pluginJson,
dsService: q.dsService,
dsCache: q.dsCache,
contextProvider: q.contextProvider,
}
}
type scopedDatasourceProvider struct {
plugin plugins.JSONData
dsService datasources.DataSourceService
dsCache datasources.CacheService
@ -58,10 +74,11 @@ type defaultPluginDatasourceProvider struct {
}
var (
_ PluginDatasourceProvider = (*defaultPluginDatasourceProvider)(nil)
_ PluginDatasourceProvider = (*scopedDatasourceProvider)(nil)
_ ScopedPluginDatasourceProvider = (*cachingDatasourceProvider)(nil)
)
func (q *defaultPluginDatasourceProvider) Get(ctx context.Context, uid string) (*v0alpha1.DataSourceConnection, error) {
func (q *scopedDatasourceProvider) Get(ctx context.Context, uid string) (*v0alpha1.DataSourceConnection, error) {
info, err := request.NamespaceInfoFrom(ctx, true)
if err != nil {
return nil, err
@ -77,7 +94,7 @@ func (q *defaultPluginDatasourceProvider) Get(ctx context.Context, uid string) (
return asConnection(ds, info.Value)
}
func (q *defaultPluginDatasourceProvider) List(ctx context.Context) (*v0alpha1.DataSourceConnectionList, error) {
func (q *scopedDatasourceProvider) List(ctx context.Context) (*v0alpha1.DataSourceConnectionList, error) {
info, err := request.NamespaceInfoFrom(ctx, true)
if err != nil {
return nil, err
@ -101,11 +118,9 @@ func (q *defaultPluginDatasourceProvider) List(ctx context.Context) (*v0alpha1.D
return result, nil
}
func (q *defaultPluginDatasourceProvider) GetInstanceSettings(ctx context.Context, uid string) (*backend.DataSourceInstanceSettings, error) {
func (q *scopedDatasourceProvider) GetInstanceSettings(ctx context.Context, uid string) (*backend.DataSourceInstanceSettings, error) {
if q.contextProvider == nil {
// NOTE!!! this is only here for the standalone example
// if we cleanup imports this can throw an error
return nil, nil
return nil, fmt.Errorf("missing contextProvider")
}
return q.contextProvider.GetDataSourceInstanceSettings(ctx, uid)
}

View File

@ -54,7 +54,7 @@ func RegisterAPIService(
features featuremgmt.FeatureToggles,
apiRegistrar builder.APIRegistrar,
pluginClient plugins.Client, // access to everything
datasources PluginDatasourceProvider,
datasources ScopedPluginDatasourceProvider,
contextProvider PluginContextWrapper,
pluginStore pluginstore.Store,
accessControl accesscontrol.AccessControl,
@ -69,7 +69,8 @@ func RegisterAPIService(
all := pluginStore.Plugins(context.Background(), plugins.TypeDataSource)
ids := []string{
"grafana-testdata-datasource",
// "prometheus",
"prometheus",
"graphite",
}
for _, ds := range all {
@ -79,7 +80,7 @@ func RegisterAPIService(
builder, err = NewDataSourceAPIBuilder(ds.JSONData,
pluginClient,
datasources,
datasources.GetDatasourceProvider(ds.JSONData),
contextProvider,
accessControl,
)

View File

@ -119,7 +119,7 @@ func (b *QueryAPIBuilder) handleQuerySingleDatasource(ctx context.Context, req d
return nil, err
}
_, rsp, err := client.QueryData(ctx, *req.Request)
code, rsp, err := client.QueryData(ctx, *req.Request)
if err == nil && rsp != nil {
for _, q := range req.Request.Queries {
if q.ResultAssertions != nil {
@ -135,6 +135,17 @@ func (b *QueryAPIBuilder) handleQuerySingleDatasource(ctx context.Context, req d
}
}
}
// Create a response object with the error when missing (happens for client errors like 404)
if rsp == nil && err != nil {
rsp = &backend.QueryDataResponse{Responses: make(backend.Responses)}
for _, q := range req.Request.Queries {
rsp.Responses[q.RefID] = backend.DataResponse{
Status: backend.Status(code),
Error: err,
}
}
}
return rsp, err
}
@ -229,6 +240,9 @@ func (b *QueryAPIBuilder) handleExpressions(ctx context.Context, req parsedReque
if qdr == nil {
qdr = &backend.QueryDataResponse{}
}
if qdr.Responses == nil {
qdr.Responses = make(backend.Responses) // avoid NPE for lookup
}
now := start // <<< this should come from the original query parser
vars := make(mathexp.Vars)
for _, expression := range req.Expressions {