mirror of https://github.com/grafana/grafana
Plugins: Remove support for deprecated backend plugin protocol version (#34127)
* 33959: Remove support for deprecated backend plugin protocol (v1) * 33959: Remove unused methods * 33959: Remove some additional unused code * 33959: Remove some additional unused code * 33959: Remove datasource plugin wrapper with test * 33959:Remove DefaultProtocolVersionpull/34357/head
parent
5042dc3b52
commit
1e8e7e34f1
@ -1,97 +0,0 @@ |
|||||||
package grpcplugin |
|
||||||
|
|
||||||
import ( |
|
||||||
"context" |
|
||||||
|
|
||||||
datasourceV1 "github.com/grafana/grafana-plugin-model/go/datasource" |
|
||||||
rendererV1 "github.com/grafana/grafana-plugin-model/go/renderer" |
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend" |
|
||||||
"github.com/grafana/grafana/pkg/infra/log" |
|
||||||
"github.com/grafana/grafana/pkg/plugins/backendplugin" |
|
||||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/instrumentation" |
|
||||||
"github.com/hashicorp/go-plugin" |
|
||||||
) |
|
||||||
|
|
||||||
type clientV1 struct { |
|
||||||
logger log.Logger |
|
||||||
datasourceV1.DatasourcePlugin |
|
||||||
rendererV1.RendererPlugin |
|
||||||
} |
|
||||||
|
|
||||||
func newClientV1(descriptor PluginDescriptor, logger log.Logger, rpcClient plugin.ClientProtocol) (pluginClient, error) { |
|
||||||
logger.Warn("Plugin uses a deprecated version of Grafana's backend plugin system which will be removed in a future release. " + |
|
||||||
"Consider upgrading to a newer plugin version or reach out to the plugin repository/developer and request an upgrade.") |
|
||||||
|
|
||||||
raw, err := rpcClient.Dispense(descriptor.pluginID) |
|
||||||
if err != nil { |
|
||||||
return nil, err |
|
||||||
} |
|
||||||
|
|
||||||
c := clientV1{ |
|
||||||
logger: logger, |
|
||||||
} |
|
||||||
if plugin, ok := raw.(datasourceV1.DatasourcePlugin); ok { |
|
||||||
c.DatasourcePlugin = instrumentDatasourcePluginV1(plugin) |
|
||||||
} |
|
||||||
|
|
||||||
if plugin, ok := raw.(rendererV1.RendererPlugin); ok { |
|
||||||
c.RendererPlugin = plugin |
|
||||||
} |
|
||||||
|
|
||||||
if descriptor.startFns.OnLegacyStart != nil { |
|
||||||
legacyClient := &LegacyClient{ |
|
||||||
DatasourcePlugin: c.DatasourcePlugin, |
|
||||||
RendererPlugin: c.RendererPlugin, |
|
||||||
} |
|
||||||
if err := descriptor.startFns.OnLegacyStart(descriptor.pluginID, legacyClient, logger); err != nil { |
|
||||||
return nil, err |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return &c, nil |
|
||||||
} |
|
||||||
|
|
||||||
func (c *clientV1) CollectMetrics(ctx context.Context) (*backend.CollectMetricsResult, error) { |
|
||||||
return nil, backendplugin.ErrMethodNotImplemented |
|
||||||
} |
|
||||||
|
|
||||||
func (c *clientV1) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { |
|
||||||
return nil, backendplugin.ErrMethodNotImplemented |
|
||||||
} |
|
||||||
|
|
||||||
func (c *clientV1) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { |
|
||||||
return backendplugin.ErrMethodNotImplemented |
|
||||||
} |
|
||||||
|
|
||||||
func (c *clientV1) SubscribeStream(ctx context.Context, request *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) { |
|
||||||
return nil, backendplugin.ErrMethodNotImplemented |
|
||||||
} |
|
||||||
|
|
||||||
func (c *clientV1) PublishStream(ctx context.Context, request *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) { |
|
||||||
return nil, backendplugin.ErrMethodNotImplemented |
|
||||||
} |
|
||||||
|
|
||||||
func (c *clientV1) RunStream(ctx context.Context, request *backend.RunStreamRequest, sender backend.StreamPacketSender) error { |
|
||||||
return backendplugin.ErrMethodNotImplemented |
|
||||||
} |
|
||||||
|
|
||||||
type datasourceV1QueryFunc func(ctx context.Context, req *datasourceV1.DatasourceRequest) (*datasourceV1.DatasourceResponse, error) |
|
||||||
|
|
||||||
func (fn datasourceV1QueryFunc) Query(ctx context.Context, req *datasourceV1.DatasourceRequest) (*datasourceV1.DatasourceResponse, error) { |
|
||||||
return fn(ctx, req) |
|
||||||
} |
|
||||||
|
|
||||||
func instrumentDatasourcePluginV1(plugin datasourceV1.DatasourcePlugin) datasourceV1.DatasourcePlugin { |
|
||||||
if plugin == nil { |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
return datasourceV1QueryFunc(func(ctx context.Context, req *datasourceV1.DatasourceRequest) (*datasourceV1.DatasourceResponse, error) { |
|
||||||
var resp *datasourceV1.DatasourceResponse |
|
||||||
err := instrumentation.InstrumentQueryDataRequest(req.Datasource.Type, func() (innerErr error) { |
|
||||||
resp, innerErr = plugin.Query(ctx, req) |
|
||||||
return |
|
||||||
}) |
|
||||||
return resp, err |
|
||||||
}) |
|
||||||
} |
|
||||||
@ -1,172 +0,0 @@ |
|||||||
package plugins |
|
||||||
|
|
||||||
import ( |
|
||||||
"context" |
|
||||||
"errors" |
|
||||||
"fmt" |
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-model/go/datasource" |
|
||||||
"github.com/grafana/grafana/pkg/components/null" |
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson" |
|
||||||
"github.com/grafana/grafana/pkg/infra/log" |
|
||||||
"github.com/grafana/grafana/pkg/models" |
|
||||||
) |
|
||||||
|
|
||||||
func newDataSourcePluginWrapper(log log.Logger, plugin datasource.DatasourcePlugin) *DatasourcePluginWrapper { |
|
||||||
return &DatasourcePluginWrapper{DatasourcePlugin: plugin, logger: log} |
|
||||||
} |
|
||||||
|
|
||||||
type DatasourcePluginWrapper struct { |
|
||||||
datasource.DatasourcePlugin |
|
||||||
logger log.Logger |
|
||||||
} |
|
||||||
|
|
||||||
func (tw *DatasourcePluginWrapper) Query(ctx context.Context, ds *models.DataSource, query DataQuery) (DataResponse, error) { |
|
||||||
jsonData, err := ds.JsonData.MarshalJSON() |
|
||||||
if err != nil { |
|
||||||
return DataResponse{}, err |
|
||||||
} |
|
||||||
|
|
||||||
pbQuery := &datasource.DatasourceRequest{ |
|
||||||
Datasource: &datasource.DatasourceInfo{ |
|
||||||
Name: ds.Name, |
|
||||||
Type: ds.Type, |
|
||||||
Url: ds.Url, |
|
||||||
Id: ds.Id, |
|
||||||
OrgId: ds.OrgId, |
|
||||||
JsonData: string(jsonData), |
|
||||||
DecryptedSecureJsonData: ds.SecureJsonData.Decrypt(), |
|
||||||
}, |
|
||||||
TimeRange: &datasource.TimeRange{ |
|
||||||
FromRaw: query.TimeRange.From, |
|
||||||
ToRaw: query.TimeRange.To, |
|
||||||
ToEpochMs: query.TimeRange.GetToAsMsEpoch(), |
|
||||||
FromEpochMs: query.TimeRange.GetFromAsMsEpoch(), |
|
||||||
}, |
|
||||||
Queries: []*datasource.Query{}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, q := range query.Queries { |
|
||||||
modelJson, err := q.Model.MarshalJSON() |
|
||||||
if err != nil { |
|
||||||
return DataResponse{}, err |
|
||||||
} |
|
||||||
|
|
||||||
pbQuery.Queries = append(pbQuery.Queries, &datasource.Query{ |
|
||||||
ModelJson: string(modelJson), |
|
||||||
IntervalMs: q.IntervalMS, |
|
||||||
RefId: q.RefID, |
|
||||||
MaxDataPoints: q.MaxDataPoints, |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
pbres, err := tw.DatasourcePlugin.Query(ctx, pbQuery) |
|
||||||
if err != nil { |
|
||||||
return DataResponse{}, err |
|
||||||
} |
|
||||||
|
|
||||||
res := DataResponse{ |
|
||||||
Results: map[string]DataQueryResult{}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, r := range pbres.Results { |
|
||||||
qr := DataQueryResult{ |
|
||||||
RefID: r.RefId, |
|
||||||
Series: []DataTimeSeries{}, |
|
||||||
Tables: []DataTable{}, |
|
||||||
} |
|
||||||
|
|
||||||
if r.Error != "" { |
|
||||||
qr.Error = errors.New(r.Error) |
|
||||||
qr.ErrorString = r.Error |
|
||||||
} |
|
||||||
|
|
||||||
if r.MetaJson != "" { |
|
||||||
metaJson, err := simplejson.NewJson([]byte(r.MetaJson)) |
|
||||||
if err != nil { |
|
||||||
tw.logger.Error("Error parsing JSON Meta field: " + err.Error()) |
|
||||||
} |
|
||||||
qr.Meta = metaJson |
|
||||||
} |
|
||||||
|
|
||||||
for _, s := range r.GetSeries() { |
|
||||||
points := DataTimeSeriesPoints{} |
|
||||||
|
|
||||||
for _, p := range s.Points { |
|
||||||
po := DataTimePoint{null.FloatFrom(p.Value), null.FloatFrom(float64(p.Timestamp))} |
|
||||||
points = append(points, po) |
|
||||||
} |
|
||||||
|
|
||||||
qr.Series = append(qr.Series, DataTimeSeries{ |
|
||||||
Name: s.Name, |
|
||||||
Tags: s.Tags, |
|
||||||
Points: points, |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
mappedTables, err := tw.mapTables(r) |
|
||||||
if err != nil { |
|
||||||
return DataResponse{}, err |
|
||||||
} |
|
||||||
qr.Tables = mappedTables |
|
||||||
|
|
||||||
res.Results[r.RefId] = qr |
|
||||||
} |
|
||||||
|
|
||||||
return res, nil |
|
||||||
} |
|
||||||
|
|
||||||
func (tw *DatasourcePluginWrapper) mapTables(r *datasource.QueryResult) ([]DataTable, error) { |
|
||||||
var tables []DataTable |
|
||||||
for _, t := range r.GetTables() { |
|
||||||
mappedTable, err := tw.mapTable(t) |
|
||||||
if err != nil { |
|
||||||
return nil, err |
|
||||||
} |
|
||||||
tables = append(tables, mappedTable) |
|
||||||
} |
|
||||||
return tables, nil |
|
||||||
} |
|
||||||
|
|
||||||
func (tw *DatasourcePluginWrapper) mapTable(t *datasource.Table) (DataTable, error) { |
|
||||||
table := DataTable{} |
|
||||||
for _, c := range t.GetColumns() { |
|
||||||
table.Columns = append(table.Columns, DataTableColumn{ |
|
||||||
Text: c.Name, |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
table.Rows = make([]DataRowValues, 0) |
|
||||||
for _, r := range t.GetRows() { |
|
||||||
row := DataRowValues{} |
|
||||||
for _, rv := range r.Values { |
|
||||||
mappedRw, err := tw.mapRowValue(rv) |
|
||||||
if err != nil { |
|
||||||
return table, err |
|
||||||
} |
|
||||||
|
|
||||||
row = append(row, mappedRw) |
|
||||||
} |
|
||||||
table.Rows = append(table.Rows, row) |
|
||||||
} |
|
||||||
|
|
||||||
return table, nil |
|
||||||
} |
|
||||||
func (tw *DatasourcePluginWrapper) mapRowValue(rv *datasource.RowValue) (interface{}, error) { |
|
||||||
switch rv.Kind { |
|
||||||
case datasource.RowValue_TYPE_NULL: |
|
||||||
return nil, nil |
|
||||||
case datasource.RowValue_TYPE_INT64: |
|
||||||
return rv.Int64Value, nil |
|
||||||
case datasource.RowValue_TYPE_BOOL: |
|
||||||
return rv.BoolValue, nil |
|
||||||
case datasource.RowValue_TYPE_STRING: |
|
||||||
return rv.StringValue, nil |
|
||||||
case datasource.RowValue_TYPE_DOUBLE: |
|
||||||
return rv.DoubleValue, nil |
|
||||||
case datasource.RowValue_TYPE_BYTES: |
|
||||||
return rv.BytesValue, nil |
|
||||||
default: |
|
||||||
return nil, fmt.Errorf("unsupported row value %v from plugin", rv.Kind) |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,86 +0,0 @@ |
|||||||
package plugins |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-model/go/datasource" |
|
||||||
"github.com/grafana/grafana/pkg/infra/log" |
|
||||||
"github.com/stretchr/testify/require" |
|
||||||
) |
|
||||||
|
|
||||||
func TestMapTables(t *testing.T) { |
|
||||||
dpw := newDataSourcePluginWrapper(log.New("test-logger"), nil) |
|
||||||
var qr = &datasource.QueryResult{} |
|
||||||
qr.Tables = append(qr.Tables, &datasource.Table{ |
|
||||||
Columns: []*datasource.TableColumn{}, |
|
||||||
Rows: nil, |
|
||||||
}) |
|
||||||
|
|
||||||
have, err := dpw.mapTables(qr) |
|
||||||
require.NoError(t, err) |
|
||||||
require.Len(t, have, 1) |
|
||||||
} |
|
||||||
|
|
||||||
func TestMapTable(t *testing.T) { |
|
||||||
dpw := newDataSourcePluginWrapper(log.New("test-logger"), nil) |
|
||||||
|
|
||||||
source := &datasource.Table{ |
|
||||||
Columns: []*datasource.TableColumn{{Name: "column1"}, {Name: "column2"}}, |
|
||||||
Rows: []*datasource.TableRow{{ |
|
||||||
Values: []*datasource.RowValue{ |
|
||||||
{ |
|
||||||
Kind: datasource.RowValue_TYPE_BOOL, |
|
||||||
BoolValue: true, |
|
||||||
}, |
|
||||||
{ |
|
||||||
Kind: datasource.RowValue_TYPE_INT64, |
|
||||||
Int64Value: 42, |
|
||||||
}, |
|
||||||
}, |
|
||||||
}}, |
|
||||||
} |
|
||||||
|
|
||||||
want := DataTable{ |
|
||||||
Columns: []DataTableColumn{{Text: "column1"}, {Text: "column2"}}, |
|
||||||
} |
|
||||||
have, err := dpw.mapTable(source) |
|
||||||
require.NoError(t, err) |
|
||||||
|
|
||||||
require.Equal(t, want.Columns, have.Columns) |
|
||||||
require.Len(t, have.Rows, 1) |
|
||||||
require.Len(t, have.Rows[0], 2) |
|
||||||
} |
|
||||||
|
|
||||||
func TestMappingRowValue(t *testing.T) { |
|
||||||
dpw := newDataSourcePluginWrapper(log.New("test-logger"), nil) |
|
||||||
|
|
||||||
boolRowValue, err := dpw.mapRowValue(&datasource.RowValue{Kind: datasource.RowValue_TYPE_BOOL, BoolValue: true}) |
|
||||||
require.NoError(t, err) |
|
||||||
haveBool, ok := boolRowValue.(bool) |
|
||||||
require.True(t, ok) |
|
||||||
require.True(t, haveBool) |
|
||||||
|
|
||||||
intRowValue, _ := dpw.mapRowValue(&datasource.RowValue{Kind: datasource.RowValue_TYPE_INT64, Int64Value: 42}) |
|
||||||
haveInt, ok := intRowValue.(int64) |
|
||||||
require.True(t, ok) |
|
||||||
require.Equal(t, int64(42), haveInt) |
|
||||||
|
|
||||||
stringRowValue, _ := dpw.mapRowValue(&datasource.RowValue{Kind: datasource.RowValue_TYPE_STRING, StringValue: "grafana"}) |
|
||||||
haveString, ok := stringRowValue.(string) |
|
||||||
require.True(t, ok) |
|
||||||
require.Equal(t, "grafana", haveString) |
|
||||||
|
|
||||||
doubleRowValue, _ := dpw.mapRowValue(&datasource.RowValue{Kind: datasource.RowValue_TYPE_DOUBLE, DoubleValue: 1.5}) |
|
||||||
haveDouble, ok := doubleRowValue.(float64) |
|
||||||
require.True(t, ok) |
|
||||||
require.Equal(t, 1.5, haveDouble) |
|
||||||
|
|
||||||
bytesRowValue, _ := dpw.mapRowValue(&datasource.RowValue{Kind: datasource.RowValue_TYPE_BYTES, BytesValue: []byte{66}}) |
|
||||||
haveBytes, ok := bytesRowValue.([]byte) |
|
||||||
require.True(t, ok) |
|
||||||
require.Equal(t, []byte{66}, haveBytes) |
|
||||||
|
|
||||||
haveNil, err := dpw.mapRowValue(&datasource.RowValue{Kind: datasource.RowValue_TYPE_NULL}) |
|
||||||
require.NoError(t, err) |
|
||||||
require.Nil(t, haveNil) |
|
||||||
} |
|
||||||
Loading…
Reference in new issue