mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
k8s/query+ds: catch query errors, fix datasourceProvider and expose prometheus (#85071)
This commit is contained in:
14
.vscode/launch.json
vendored
14
.vscode/launch.json
vendored
@@ -23,6 +23,20 @@
|
|||||||
"--secure-port=8443",
|
"--secure-port=8443",
|
||||||
"--runtime-config=testdata.datasource.grafana.app/v0alpha1=true"]
|
"--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",
|
"name": "Attach to Chrome",
|
||||||
"port": 9222,
|
"port": 9222,
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ type PluginDatasourceProvider interface {
|
|||||||
GetInstanceSettings(ctx context.Context, uid string) (*backend.DataSourceInstanceSettings, error)
|
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
|
// PluginContext requires adding system settings (feature flags, etc) to the datasource config
|
||||||
type PluginContextWrapper interface {
|
type PluginContextWrapper interface {
|
||||||
PluginContextForDataSource(ctx context.Context, datasourceSettings *backend.DataSourceInstanceSettings) (backend.PluginContext, error)
|
PluginContextForDataSource(ctx context.Context, datasourceSettings *backend.DataSourceInstanceSettings) (backend.PluginContext, error)
|
||||||
@@ -39,18 +43,30 @@ type PluginContextWrapper interface {
|
|||||||
func ProvideDefaultPluginConfigs(
|
func ProvideDefaultPluginConfigs(
|
||||||
dsService datasources.DataSourceService,
|
dsService datasources.DataSourceService,
|
||||||
dsCache datasources.CacheService,
|
dsCache datasources.CacheService,
|
||||||
contextProvider *plugincontext.Provider) PluginDatasourceProvider {
|
contextProvider *plugincontext.Provider) ScopedPluginDatasourceProvider {
|
||||||
return &defaultPluginDatasourceProvider{
|
return &cachingDatasourceProvider{
|
||||||
plugin: plugins.JSONData{
|
|
||||||
ID: datasources.DS_TESTDATA,
|
|
||||||
},
|
|
||||||
dsService: dsService,
|
dsService: dsService,
|
||||||
dsCache: dsCache,
|
dsCache: dsCache,
|
||||||
contextProvider: contextProvider,
|
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
|
plugin plugins.JSONData
|
||||||
dsService datasources.DataSourceService
|
dsService datasources.DataSourceService
|
||||||
dsCache datasources.CacheService
|
dsCache datasources.CacheService
|
||||||
@@ -58,10 +74,11 @@ type defaultPluginDatasourceProvider struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
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)
|
info, err := request.NamespaceInfoFrom(ctx, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -77,7 +94,7 @@ func (q *defaultPluginDatasourceProvider) Get(ctx context.Context, uid string) (
|
|||||||
return asConnection(ds, info.Value)
|
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)
|
info, err := request.NamespaceInfoFrom(ctx, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -101,11 +118,9 @@ func (q *defaultPluginDatasourceProvider) List(ctx context.Context) (*v0alpha1.D
|
|||||||
return result, nil
|
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 {
|
if q.contextProvider == nil {
|
||||||
// NOTE!!! this is only here for the standalone example
|
return nil, fmt.Errorf("missing contextProvider")
|
||||||
// if we cleanup imports this can throw an error
|
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
return q.contextProvider.GetDataSourceInstanceSettings(ctx, uid)
|
return q.contextProvider.GetDataSourceInstanceSettings(ctx, uid)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ func RegisterAPIService(
|
|||||||
features featuremgmt.FeatureToggles,
|
features featuremgmt.FeatureToggles,
|
||||||
apiRegistrar builder.APIRegistrar,
|
apiRegistrar builder.APIRegistrar,
|
||||||
pluginClient plugins.Client, // access to everything
|
pluginClient plugins.Client, // access to everything
|
||||||
datasources PluginDatasourceProvider,
|
datasources ScopedPluginDatasourceProvider,
|
||||||
contextProvider PluginContextWrapper,
|
contextProvider PluginContextWrapper,
|
||||||
pluginStore pluginstore.Store,
|
pluginStore pluginstore.Store,
|
||||||
accessControl accesscontrol.AccessControl,
|
accessControl accesscontrol.AccessControl,
|
||||||
@@ -69,7 +69,8 @@ func RegisterAPIService(
|
|||||||
all := pluginStore.Plugins(context.Background(), plugins.TypeDataSource)
|
all := pluginStore.Plugins(context.Background(), plugins.TypeDataSource)
|
||||||
ids := []string{
|
ids := []string{
|
||||||
"grafana-testdata-datasource",
|
"grafana-testdata-datasource",
|
||||||
// "prometheus",
|
"prometheus",
|
||||||
|
"graphite",
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ds := range all {
|
for _, ds := range all {
|
||||||
@@ -79,7 +80,7 @@ func RegisterAPIService(
|
|||||||
|
|
||||||
builder, err = NewDataSourceAPIBuilder(ds.JSONData,
|
builder, err = NewDataSourceAPIBuilder(ds.JSONData,
|
||||||
pluginClient,
|
pluginClient,
|
||||||
datasources,
|
datasources.GetDatasourceProvider(ds.JSONData),
|
||||||
contextProvider,
|
contextProvider,
|
||||||
accessControl,
|
accessControl,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ func (b *QueryAPIBuilder) handleQuerySingleDatasource(ctx context.Context, req d
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, rsp, err := client.QueryData(ctx, *req.Request)
|
code, rsp, err := client.QueryData(ctx, *req.Request)
|
||||||
if err == nil && rsp != nil {
|
if err == nil && rsp != nil {
|
||||||
for _, q := range req.Request.Queries {
|
for _, q := range req.Request.Queries {
|
||||||
if q.ResultAssertions != nil {
|
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
|
return rsp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,6 +240,9 @@ func (b *QueryAPIBuilder) handleExpressions(ctx context.Context, req parsedReque
|
|||||||
if qdr == nil {
|
if qdr == nil {
|
||||||
qdr = &backend.QueryDataResponse{}
|
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
|
now := start // <<< this should come from the original query parser
|
||||||
vars := make(mathexp.Vars)
|
vars := make(mathexp.Vars)
|
||||||
for _, expression := range req.Expressions {
|
for _, expression := range req.Expressions {
|
||||||
|
|||||||
Reference in New Issue
Block a user