SSE: Add functions that determine NodeType by UID and construct a data source struct from NodeType (#70106)

* add NodeTypeFromDatasourceUID and DataSourceModelFromNodeType()
* deprecate expr.DataSourceModel
* replace usages of IsDataSource to NodeTypeFromDatasourceUID 
* replace usages of DataSourceModel to DataSourceModelFromNodeType()
This commit is contained in:
Yuri Tseretyan 2023-06-16 13:05:06 -04:00 committed by GitHub
parent 3d15d54a71
commit 842f33580e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 76 additions and 40 deletions

View File

@ -166,11 +166,13 @@ func (s *Service) buildGraph(req *Request) (*simple.DirectedGraph, error) {
}
var node Node
if IsDataSource(rn.DataSource.UID) {
node, err = buildCMDNode(dp, rn)
} else {
switch NodeTypeFromDatasourceUID(query.DataSource.UID) {
case TypeDatasourceNode:
node, err = s.buildDSNode(dp, rn, req)
case TypeCMDNode:
node, err = buildCMDNode(dp, rn)
default:
err = fmt.Errorf("unsupported node type '%s'", NodeTypeFromDatasourceUID(query.DataSource.UID))
}
if err != nil {

View File

@ -22,7 +22,7 @@ func TestServicebuildPipeLine(t *testing.T) {
Queries: []Query{
{
RefID: "A",
DataSource: DataSourceModel(),
DataSource: dataSourceModel(),
JSON: json.RawMessage(`{
"expression": "B",
"reducer": "mean",
@ -46,7 +46,7 @@ func TestServicebuildPipeLine(t *testing.T) {
Queries: []Query{
{
RefID: "A",
DataSource: DataSourceModel(),
DataSource: dataSourceModel(),
JSON: json.RawMessage(`{
"expression": "$B",
"type": "math"
@ -54,7 +54,7 @@ func TestServicebuildPipeLine(t *testing.T) {
},
{
RefID: "B",
DataSource: DataSourceModel(),
DataSource: dataSourceModel(),
JSON: json.RawMessage(`{
"expression": "$A",
"type": "math"
@ -70,7 +70,7 @@ func TestServicebuildPipeLine(t *testing.T) {
Queries: []Query{
{
RefID: "A",
DataSource: DataSourceModel(),
DataSource: dataSourceModel(),
JSON: json.RawMessage(`{
"expression": "$A",
"type": "math"
@ -86,7 +86,7 @@ func TestServicebuildPipeLine(t *testing.T) {
Queries: []Query{
{
RefID: "A",
DataSource: DataSourceModel(),
DataSource: dataSourceModel(),
JSON: json.RawMessage(`{
"expression": "$B",
"type": "math"
@ -102,7 +102,7 @@ func TestServicebuildPipeLine(t *testing.T) {
Queries: []Query{
{
RefID: "A",
DataSource: DataSourceModel(),
DataSource: dataSourceModel(),
JSON: json.RawMessage(`{
"type": "classic_conditions",
"conditions": [
@ -133,7 +133,7 @@ func TestServicebuildPipeLine(t *testing.T) {
},
{
RefID: "B",
DataSource: DataSourceModel(),
DataSource: dataSourceModel(),
JSON: json.RawMessage(`{
"expression": "C",
"reducer": "mean",
@ -157,7 +157,7 @@ func TestServicebuildPipeLine(t *testing.T) {
Queries: []Query{
{
RefID: "A",
DataSource: DataSourceModel(),
DataSource: dataSourceModel(),
JSON: json.RawMessage(`{
"type": "classic_conditions",
"conditions": [
@ -188,7 +188,7 @@ func TestServicebuildPipeLine(t *testing.T) {
},
{
RefID: "B",
DataSource: DataSourceModel(),
DataSource: dataSourceModel(),
JSON: json.RawMessage(`{
"expression": "A",
"reducer": "mean",
@ -212,7 +212,7 @@ func TestServicebuildPipeLine(t *testing.T) {
Queries: []Query{
{
RefID: "A",
DataSource: DataSourceModel(),
DataSource: dataSourceModel(),
JSON: json.RawMessage(`{
"expression": "B",
"reducer": "mean",

View File

@ -2,6 +2,8 @@ package expr
import (
"context"
"errors"
"fmt"
"time"
"github.com/grafana/grafana-plugin-sdk-go/backend"
@ -39,6 +41,15 @@ func IsDataSource(uid string) bool {
return uid == DatasourceUID || uid == OldDatasourceUID
}
// NodeTypeFromDatasourceUID returns NodeType depending on the UID of the data source: TypeCMDNode if UID is DatasourceUID
// or OldDatasourceUID, and TypeDatasourceNode otherwise.
func NodeTypeFromDatasourceUID(uid string) NodeType {
if IsDataSource(uid) {
return TypeCMDNode
}
return TypeDatasourceNode
}
// Service is service representation for expression handling.
type Service struct {
cfg *setting.Cfg
@ -46,6 +57,8 @@ type Service struct {
pCtxProvider *plugincontext.Provider
features featuremgmt.FeatureToggles
pluginsClient backend.CallResourceHandler
tracer tracing.Tracer
metrics *metrics
}
@ -53,12 +66,13 @@ type Service struct {
func ProvideService(cfg *setting.Cfg, pluginClient plugins.Client, pCtxProvider *plugincontext.Provider,
features featuremgmt.FeatureToggles, registerer prometheus.Registerer, tracer tracing.Tracer) *Service {
return &Service{
cfg: cfg,
dataService: pluginClient,
pCtxProvider: pCtxProvider,
features: features,
tracer: tracer,
metrics: newMetrics(registerer),
cfg: cfg,
dataService: pluginClient,
pCtxProvider: pCtxProvider,
features: features,
tracer: tracer,
metrics: newMetrics(registerer),
pluginsClient: pluginClient,
}
}
@ -91,13 +105,27 @@ func (s *Service) ExecutePipeline(ctx context.Context, now time.Time, pipeline D
return res, nil
}
func DataSourceModel() *datasources.DataSource {
return &datasources.DataSource{
ID: DatasourceID,
UID: DatasourceUID,
Name: DatasourceUID,
Type: DatasourceType,
JsonData: simplejson.New(),
SecureJsonData: make(map[string][]byte),
// Create a datasources.DataSource struct from NodeType. Returns error if kind is TypeDatasourceNode or unknown one.
func DataSourceModelFromNodeType(kind NodeType) (*datasources.DataSource, error) {
switch kind {
case TypeCMDNode:
return &datasources.DataSource{
ID: DatasourceID,
UID: DatasourceUID,
Name: DatasourceUID,
Type: DatasourceType,
JsonData: simplejson.New(),
SecureJsonData: make(map[string][]byte),
}, nil
case TypeDatasourceNode:
return nil, errors.New("cannot create expression data source for data source kind")
default:
return nil, fmt.Errorf("cannot create expression data source for '%s' kind", kind)
}
}
// Deprecated. Use DataSourceModelFromNodeType instead
func DataSourceModel() *datasources.DataSource {
d, _ := DataSourceModelFromNodeType(TypeCMDNode)
return d
}

View File

@ -62,7 +62,7 @@ func TestService(t *testing.T) {
},
{
RefID: "B",
DataSource: DataSourceModel(),
DataSource: dataSourceModel(),
JSON: json.RawMessage(`{ "datasource": { "uid": "__expr__", "type": "__expr__"}, "type": "math", "expression": "$A * 2" }`),
},
}
@ -124,3 +124,8 @@ func (me *mockEndpoint) QueryData(ctx context.Context, req *backend.QueryDataReq
}
return resp, nil
}
func dataSourceModel() *datasources.DataSource {
d, _ := DataSourceModelFromNodeType(TypeCMDNode)
return d
}

View File

@ -269,13 +269,14 @@ func getExprRequest(ctx EvaluationContext, data []models.AlertQuery, dsCacheServ
ds, ok := datasources[q.DatasourceUID]
if !ok {
if expr.IsDataSource(q.DatasourceUID) {
ds = expr.DataSourceModel()
} else {
switch nodeType := expr.NodeTypeFromDatasourceUID(q.DatasourceUID); nodeType {
case expr.TypeCMDNode:
ds, err = expr.DataSourceModelFromNodeType(nodeType)
case expr.TypeDatasourceNode:
ds, err = dsCacheService.GetDatasourceByUID(ctx.Ctx, q.DatasourceUID, ctx.User, false /*skipCache*/)
if err != nil {
return nil, fmt.Errorf("failed to build query '%s': %w", q.RefID, err)
}
}
if err != nil {
return nil, fmt.Errorf("failed to build query '%s': %w", q.RefID, err)
}
datasources[q.DatasourceUID] = ds
}
@ -621,7 +622,7 @@ func (e *evaluatorImpl) Validate(ctx EvaluationContext, condition models.Conditi
return err
}
for _, query := range req.Queries {
if query.DataSource == nil || expr.IsDataSource(query.DataSource.UID) {
if query.DataSource == nil || expr.NodeTypeFromDatasourceUID(query.DataSource.UID) != expr.TypeDatasourceNode {
continue
}
p, found := e.pluginsStore.Plugin(ctx.Ctx, query.DataSource.Type)

View File

@ -113,7 +113,7 @@ func (aq *AlertQuery) setModelProps() error {
// IsExpression returns true if the alert query is an expression.
func (aq *AlertQuery) IsExpression() (bool, error) {
return expr.IsDataSource(aq.DatasourceUID), nil
return expr.NodeTypeFromDatasourceUID(aq.DatasourceUID) == expr.TypeCMDNode, nil
}
// setMaxDatapoints sets the model maxDataPoints if it's missing or invalid

View File

@ -269,7 +269,7 @@ func (s *ServiceImpl) parseMetricRequest(ctx context.Context, user *user.SignedI
}
datasourcesByUid[ds.UID] = ds
if expr.IsDataSource(ds.UID) {
if expr.NodeTypeFromDatasourceUID(ds.UID) != expr.TypeDatasourceNode {
req.hasExpression = true
} else {
req.dsTypes[ds.Type] = true
@ -321,8 +321,8 @@ func (s *ServiceImpl) getDataSourceFromQuery(ctx context.Context, user *user.Sig
return ds, nil
}
if expr.IsDataSource(uid) {
return expr.DataSourceModel(), nil
if kind := expr.NodeTypeFromDatasourceUID(uid); kind != expr.TypeDatasourceNode {
return expr.DataSourceModelFromNodeType(kind)
}
if uid == grafanads.DatasourceUID {