mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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 DefaultProtocolVersion
This commit is contained in:
parent
5042dc3b52
commit
1e8e7e34f1
1
go.mod
1
go.mod
@ -51,7 +51,6 @@ require (
|
||||
github.com/gosimple/slug v1.9.0
|
||||
github.com/grafana/grafana-aws-sdk v0.4.0
|
||||
github.com/grafana/grafana-live-sdk v0.0.6
|
||||
github.com/grafana/grafana-plugin-model v0.0.0-20190930120109-1fc953a61fb4
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.98.0
|
||||
github.com/grafana/loki v1.6.2-0.20210510132741-f408e05ad426
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
|
||||
|
4
go.sum
4
go.sum
@ -922,8 +922,6 @@ github.com/grafana/grafana-aws-sdk v0.4.0 h1:JmTaXfOJ/ydHSWH9kEt8Yhfb9kAhIW4LUOO
|
||||
github.com/grafana/grafana-aws-sdk v0.4.0/go.mod h1:+pPo5U+pX0zWimR7YBc7ASeSQfbRkcTyQYqMiAj7G5U=
|
||||
github.com/grafana/grafana-live-sdk v0.0.6 h1:P1QFn0ZradOJp3zVpfG0STZMP+pgZrW0e0zvpqOrYVI=
|
||||
github.com/grafana/grafana-live-sdk v0.0.6/go.mod h1:f15hHmWyLdFjmuWLsjeKeZnq/HnNQ3QkoPcaEww45AY=
|
||||
github.com/grafana/grafana-plugin-model v0.0.0-20190930120109-1fc953a61fb4 h1:SPdxCL9BChFTlyi0Khv64vdCW4TMna8+sxL7+Chx+Ag=
|
||||
github.com/grafana/grafana-plugin-model v0.0.0-20190930120109-1fc953a61fb4/go.mod h1:nc0XxBzjeGcrMltCDw269LoWF9S8ibhgxolCdA1R8To=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.79.0/go.mod h1:NvxLzGkVhnoBKwzkst6CFfpMFKwAdIUZ1q8ssuLeF60=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.91.0/go.mod h1:Ot3k7nY7P6DXmUsDgKvNB7oG1v7PRyTdmnYVoS554bU=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.98.0 h1:LW69nbYfteelPcyogFNozAbJyaLksKdPtO3t4i3shMQ=
|
||||
@ -992,7 +990,6 @@ github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iP
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
|
||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||
github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
|
||||
github.com/hashicorp/go-plugin v1.2.2/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0=
|
||||
github.com/hashicorp/go-plugin v1.4.0 h1:b0O7rs5uiJ99Iu9HugEzsM67afboErkHUWddUSpUO3A=
|
||||
github.com/hashicorp/go-plugin v1.4.0/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ=
|
||||
@ -2140,7 +2137,6 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -3,8 +3,6 @@ package grpcplugin
|
||||
import (
|
||||
"os/exec"
|
||||
|
||||
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/grpcplugin"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
@ -12,19 +10,12 @@ import (
|
||||
goplugin "github.com/hashicorp/go-plugin"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultProtocolVersion is the protocol version assumed for legacy clients that don't specify
|
||||
// a particular version or version 1 during their handshake. This is currently the version used
|
||||
// since Grafana launched support for backend plugins.
|
||||
DefaultProtocolVersion = 1
|
||||
)
|
||||
|
||||
// Handshake is the HandshakeConfig used to configure clients and servers.
|
||||
var handshake = goplugin.HandshakeConfig{
|
||||
// The ProtocolVersion is the version that must match between Grafana core
|
||||
// and Grafana plugins. This should be bumped whenever a (breaking) change
|
||||
// happens in one or the other that makes it so that they can't safely communicate.
|
||||
ProtocolVersion: DefaultProtocolVersion,
|
||||
ProtocolVersion: grpcplugin.ProtocolVersion,
|
||||
|
||||
// The magic cookie values should NEVER be changed.
|
||||
MagicCookieKey: grpcplugin.MagicCookieKey,
|
||||
@ -47,15 +38,11 @@ func newClientConfig(executablePath string, env []string, logger log.Logger,
|
||||
}
|
||||
}
|
||||
|
||||
// LegacyStartFunc callback function called when a plugin with old plugin protocol is started.
|
||||
type LegacyStartFunc func(pluginID string, client *LegacyClient, logger log.Logger) error
|
||||
|
||||
// StartFunc callback function called when a plugin with current plugin protocol version is started.
|
||||
type StartFunc func(pluginID string, client *Client, logger log.Logger) error
|
||||
|
||||
// PluginStartFuncs functions called for plugin when started.
|
||||
type PluginStartFuncs struct {
|
||||
OnLegacyStart LegacyStartFunc
|
||||
OnStart StartFunc
|
||||
}
|
||||
|
||||
@ -86,9 +73,6 @@ func NewBackendPlugin(pluginID, executablePath string, startFns PluginStartFuncs
|
||||
executablePath: executablePath,
|
||||
managed: true,
|
||||
versionedPlugins: map[int]goplugin.PluginSet{
|
||||
DefaultProtocolVersion: {
|
||||
pluginID: &datasourceV1.DatasourcePluginImpl{},
|
||||
},
|
||||
grpcplugin.ProtocolVersion: getV2PluginSet(),
|
||||
},
|
||||
startFns: startFns,
|
||||
@ -102,21 +86,12 @@ func NewRendererPlugin(pluginID, executablePath string, startFns PluginStartFunc
|
||||
executablePath: executablePath,
|
||||
managed: false,
|
||||
versionedPlugins: map[int]goplugin.PluginSet{
|
||||
DefaultProtocolVersion: {
|
||||
pluginID: &rendererV1.RendererPluginImpl{},
|
||||
},
|
||||
grpcplugin.ProtocolVersion: getV2PluginSet(),
|
||||
},
|
||||
startFns: startFns,
|
||||
})
|
||||
}
|
||||
|
||||
// LegacyClient client for communicating with a plugin using the v1 plugin protocol.
|
||||
type LegacyClient struct {
|
||||
DatasourcePlugin datasourceV1.DatasourcePlugin
|
||||
RendererPlugin rendererV1.RendererPlugin
|
||||
}
|
||||
|
||||
// Client client for communicating with a plugin using the current (v2) plugin protocol.
|
||||
type Client struct {
|
||||
DataPlugin grpcplugin.DataClient
|
||||
|
@ -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
|
||||
})
|
||||
}
|
@ -59,17 +59,13 @@ func (p *grpcPlugin) Start(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.client.NegotiatedVersion() > 1 {
|
||||
if p.client.NegotiatedVersion() < 2 {
|
||||
return errors.New("plugin protocol version not supported")
|
||||
}
|
||||
p.pluginClient, err = newClientV2(p.descriptor, p.logger, rpcClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
p.pluginClient, err = newClientV1(p.descriptor, p.logger, rpcClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if p.pluginClient == nil {
|
||||
return errors.New("no compatible plugin implementation found")
|
||||
|
@ -34,7 +34,6 @@ type DataSourcePlugin struct {
|
||||
SDK bool `json:"sdk,omitempty"`
|
||||
|
||||
client *grpcplugin.Client
|
||||
legacyClient *grpcplugin.LegacyClient
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
@ -48,7 +47,6 @@ func (p *DataSourcePlugin) Load(decoder *json.Decoder, base *PluginBase, backend
|
||||
cmd := ComposePluginStartCommand(p.Executable)
|
||||
fullpath := filepath.Join(base.PluginDir, cmd)
|
||||
factory := grpcplugin.NewBackendPlugin(p.Id, fullpath, grpcplugin.PluginStartFuncs{
|
||||
OnLegacyStart: p.onLegacyPluginStart,
|
||||
OnStart: p.onPluginStart,
|
||||
})
|
||||
if err := backendPluginManager.RegisterAndStart(context.Background(), p.Id, factory); err != nil {
|
||||
@ -64,24 +62,12 @@ func (p *DataSourcePlugin) DataQuery(ctx context.Context, dsInfo *models.DataSou
|
||||
return DataResponse{}, fmt.Errorf("plugin %q can't handle data queries", p.Id)
|
||||
}
|
||||
|
||||
if p.client != nil {
|
||||
endpoint := newDataSourcePluginWrapperV2(p.logger, p.Id, p.Type, p.client.DataPlugin)
|
||||
return endpoint.Query(ctx, dsInfo, query)
|
||||
}
|
||||
|
||||
endpoint := newDataSourcePluginWrapper(p.logger, p.legacyClient.DatasourcePlugin)
|
||||
return endpoint.Query(ctx, dsInfo, query)
|
||||
}
|
||||
|
||||
func (p *DataSourcePlugin) onLegacyPluginStart(pluginID string, client *grpcplugin.LegacyClient, logger log.Logger) error {
|
||||
p.legacyClient = client
|
||||
p.logger = logger
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *DataSourcePlugin) CanHandleDataQueries() bool {
|
||||
return p.client != nil || p.legacyClient != nil
|
||||
return p.client != nil
|
||||
}
|
||||
|
||||
func (p *DataSourcePlugin) onPluginStart(pluginID string, client *grpcplugin.Client, logger log.Logger) error {
|
||||
|
@ -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)
|
||||
}
|
@ -5,7 +5,6 @@ import (
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
|
||||
pluginModel "github.com/grafana/grafana-plugin-model/go/renderer"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/grpcplugin"
|
||||
@ -17,7 +16,6 @@ type RendererPlugin struct {
|
||||
FrontendPluginBase
|
||||
|
||||
Executable string `json:"executable,omitempty"`
|
||||
GrpcPluginV1 pluginModel.RendererPlugin
|
||||
GrpcPluginV2 pluginextensionv2.RendererPlugin
|
||||
backendPluginManager backendplugin.Manager
|
||||
}
|
||||
@ -33,7 +31,6 @@ func (r *RendererPlugin) Load(decoder *json.Decoder, base *PluginBase,
|
||||
cmd := ComposePluginStartCommand("plugin_start")
|
||||
fullpath := filepath.Join(base.PluginDir, cmd)
|
||||
factory := grpcplugin.NewRendererPlugin(r.Id, fullpath, grpcplugin.PluginStartFuncs{
|
||||
OnLegacyStart: r.onLegacyPluginStart,
|
||||
OnStart: r.onPluginStart,
|
||||
})
|
||||
if err := backendPluginManager.Register(r.Id, factory); err != nil {
|
||||
@ -51,11 +48,6 @@ func (r *RendererPlugin) Start(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RendererPlugin) onLegacyPluginStart(pluginID string, client *grpcplugin.LegacyClient, logger log.Logger) error {
|
||||
r.GrpcPluginV1 = client.RendererPlugin
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RendererPlugin) onPluginStart(pluginID string, client *grpcplugin.Client, logger log.Logger) error {
|
||||
r.GrpcPluginV2 = client.RendererPlugin
|
||||
return nil
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
pluginModel "github.com/grafana/grafana-plugin-model/go/renderer"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/pluginextensionv2"
|
||||
)
|
||||
|
||||
@ -19,48 +18,6 @@ func (rs *RenderingService) renderViaPlugin(ctx context.Context, renderKey strin
|
||||
ctx, cancel := context.WithTimeout(ctx, opts.Timeout+time.Second*2)
|
||||
defer cancel()
|
||||
|
||||
if rs.pluginInfo.GrpcPluginV2 != nil {
|
||||
return rs.renderViaPluginV2(ctx, renderKey, opts)
|
||||
}
|
||||
|
||||
return rs.renderViaPluginV1(ctx, renderKey, opts)
|
||||
}
|
||||
|
||||
func (rs *RenderingService) renderViaPluginV1(ctx context.Context, renderKey string, opts Opts) (*RenderResult, error) {
|
||||
filePath, err := rs.getNewFilePath(RenderPNG)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := &pluginModel.RenderRequest{
|
||||
Url: rs.getURL(opts.Path),
|
||||
Width: int32(opts.Width),
|
||||
Height: int32(opts.Height),
|
||||
FilePath: filePath,
|
||||
Timeout: int32(opts.Timeout.Seconds()),
|
||||
RenderKey: renderKey,
|
||||
Encoding: opts.Encoding,
|
||||
Timezone: isoTimeOffsetToPosixTz(opts.Timezone),
|
||||
Domain: rs.domain,
|
||||
}
|
||||
rs.log.Debug("calling renderer plugin", "req", req)
|
||||
|
||||
rsp, err := rs.pluginInfo.GrpcPluginV1.Render(ctx, req)
|
||||
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
||||
rs.log.Info("Rendering timed out")
|
||||
return nil, ErrTimeout
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rsp.Error != "" {
|
||||
return nil, fmt.Errorf("rendering failed: %v", rsp.Error)
|
||||
}
|
||||
|
||||
return &RenderResult{FilePath: filePath}, nil
|
||||
}
|
||||
|
||||
func (rs *RenderingService) renderViaPluginV2(ctx context.Context, renderKey string, opts Opts) (*RenderResult, error) {
|
||||
filePath, err := rs.getNewFilePath(RenderPNG)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
Loading…
Reference in New Issue
Block a user