Backend plugins: Updates due to changes in SDK (#22649)

Use v0.20.0 of SDK
This commit is contained in:
Marcus Efraimsson
2020-03-10 12:59:03 +01:00
committed by GitHub
parent 805abdfa2a
commit c12245bbb3
141 changed files with 2482 additions and 3121 deletions
+29 -18
View File
@@ -33,7 +33,7 @@ type BackendPlugin struct {
logger log.Logger
startFns PluginStartFuncs
diagnostics DiagnosticsPlugin
core CorePlugin
resource ResourcePlugin
}
func (p *BackendPlugin) start(ctx context.Context) error {
@@ -52,7 +52,12 @@ func (p *BackendPlugin) start(ctx context.Context) error {
return err
}
rawBackend, err := rpcClient.Dispense("backend")
rawResource, err := rpcClient.Dispense("resource")
if err != nil {
return err
}
rawData, err := rpcClient.Dispense("data")
if err != nil {
return err
}
@@ -69,10 +74,16 @@ func (p *BackendPlugin) start(ctx context.Context) error {
}
client = &Client{}
if rawBackend != nil {
if plugin, ok := rawBackend.(CorePlugin); ok {
p.core = plugin
client.CorePlugin = plugin
if rawResource != nil {
if plugin, ok := rawResource.(ResourcePlugin); ok {
p.resource = plugin
client.ResourcePlugin = plugin
}
}
if rawData != nil {
if plugin, ok := rawData.(DataPlugin); ok {
client.DataPlugin = plugin
}
}
@@ -138,7 +149,7 @@ func (p *BackendPlugin) CollectMetrics(ctx context.Context, ch chan<- prometheus
return nil
}
res, err := p.diagnostics.CollectMetrics(ctx, &pluginv2.CollectMetrics_Request{})
res, err := p.diagnostics.CollectMetrics(ctx, &pluginv2.CollectMetricsRequest{})
if err != nil {
if st, ok := status.FromError(err); ok {
if st.Code() == codes.Unimplemented {
@@ -174,19 +185,19 @@ func (p *BackendPlugin) CollectMetrics(ctx context.Context, ch chan<- prometheus
return nil
}
func (p *BackendPlugin) checkHealth(ctx context.Context) (*pluginv2.CheckHealth_Response, error) {
func (p *BackendPlugin) checkHealth(ctx context.Context) (*pluginv2.CheckHealthResponse, error) {
if p.diagnostics == nil || p.client == nil || p.client.Exited() {
return &pluginv2.CheckHealth_Response{
Status: pluginv2.CheckHealth_Response_UNKNOWN,
return &pluginv2.CheckHealthResponse{
Status: pluginv2.CheckHealthResponse_UNKNOWN,
}, nil
}
res, err := p.diagnostics.CheckHealth(ctx, &pluginv2.CheckHealth_Request{})
res, err := p.diagnostics.CheckHealth(ctx, &pluginv2.CheckHealthRequest{})
if err != nil {
if st, ok := status.FromError(err); ok {
if st.Code() == codes.Unimplemented {
return &pluginv2.CheckHealth_Response{
Status: pluginv2.CheckHealth_Response_UNKNOWN,
return &pluginv2.CheckHealthResponse{
Status: pluginv2.CheckHealthResponse_UNKNOWN,
Message: "Health check not implemented",
}, nil
}
@@ -200,13 +211,13 @@ func (p *BackendPlugin) checkHealth(ctx context.Context) (*pluginv2.CheckHealth_
func (p *BackendPlugin) callResource(ctx context.Context, req CallResourceRequest) (callResourceResultStream, error) {
p.logger.Debug("Calling resource", "path", req.Path, "method", req.Method)
if p.core == nil || p.client == nil || p.client.Exited() {
if p.resource == nil || p.client == nil || p.client.Exited() {
return nil, errors.New("plugin not running, cannot call resource")
}
reqHeaders := map[string]*pluginv2.CallResource_StringList{}
reqHeaders := map[string]*pluginv2.StringList{}
for k, v := range req.Headers {
reqHeaders[k] = &pluginv2.CallResource_StringList{Values: v}
reqHeaders[k] = &pluginv2.StringList{Values: v}
}
jsonDataBytes, err := req.Config.JSONData.ToDB()
@@ -214,7 +225,7 @@ func (p *BackendPlugin) callResource(ctx context.Context, req CallResourceReques
return nil, err
}
protoReq := &pluginv2.CallResource_Request{
protoReq := &pluginv2.CallResourceRequest{
Config: &pluginv2.PluginConfig{
OrgId: req.Config.OrgID,
PluginId: req.Config.PluginID,
@@ -251,7 +262,7 @@ func (p *BackendPlugin) callResource(ctx context.Context, req CallResourceReques
}
}
protoStream, err := p.core.CallResource(ctx, protoReq)
protoStream, err := p.resource.CallResource(ctx, protoReq)
if err != nil {
if st, ok := status.FromError(err); ok {
if st.Code() == codes.Unimplemented {
+11 -7
View File
@@ -1,7 +1,6 @@
package backendplugin
import (
"context"
"os/exec"
"github.com/grafana/grafana-plugin-sdk-go/backend/plugin"
@@ -10,7 +9,6 @@ import (
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/genproto/pluginv2"
goplugin "github.com/hashicorp/go-plugin"
)
@@ -77,7 +75,8 @@ func NewBackendPluginDescriptor(pluginID, executablePath string, startFns Plugin
},
plugin.ProtocolVersion: {
"diagnostics": &plugin.DiagnosticsGRPCPlugin{},
"backend": &plugin.CoreGRPCPlugin{},
"resource": &plugin.ResourceGRPCPlugin{},
"data": &plugin.DataGRPCPlugin{},
"transform": &plugin.TransformGRPCPlugin{},
},
},
@@ -105,12 +104,16 @@ type DiagnosticsPlugin interface {
plugin.DiagnosticsServer
}
type CorePlugin interface {
plugin.CoreClient
type ResourcePlugin interface {
plugin.ResourceClient
}
type DataPlugin interface {
plugin.DataClient
}
type TransformPlugin interface {
DataQuery(ctx context.Context, req *pluginv2.DataQueryRequest, callback plugin.TransformCallBack) (*pluginv2.DataQueryResponse, error)
plugin.TransformClient
}
// LegacyClient client for communicating with a plugin using the old plugin protocol.
@@ -121,6 +124,7 @@ type LegacyClient struct {
// Client client for communicating with a plugin using the current plugin protocol.
type Client struct {
CorePlugin CorePlugin
ResourcePlugin ResourcePlugin
DataPlugin DataPlugin
TransformPlugin TransformPlugin
}
+4 -4
View File
@@ -43,12 +43,12 @@ type CheckHealthResult struct {
JSONDetails string
}
func checkHealthResultFromProto(protoResp *pluginv2.CheckHealth_Response) *CheckHealthResult {
func checkHealthResultFromProto(protoResp *pluginv2.CheckHealthResponse) *CheckHealthResult {
status := HealthStatusUnknown
switch protoResp.Status {
case pluginv2.CheckHealth_Response_ERROR:
case pluginv2.CheckHealthResponse_ERROR:
status = HealthStatusError
case pluginv2.CheckHealth_Response_OK:
case pluginv2.CheckHealthResponse_OK:
status = HealthStatusOk
}
@@ -102,7 +102,7 @@ type callResourceResultStream interface {
}
type callResourceResultStreamImpl struct {
stream pluginv2.Core_CallResourceClient
stream pluginv2.Resource_CallResourceClient
}
func (s *callResourceResultStreamImpl) Recv() (*CallResourceResult, error) {
@@ -1,137 +0,0 @@
package resource
import (
"bytes"
"net/http"
"github.com/grafana/grafana-plugin-sdk-go/genproto/pluginv2"
)
// ResourceResponseWriter is an implementation of http.ResponseWriter that
// records its mutations for later inspection in tests.
type ResourceResponseWriter struct {
// Code is the HTTP response code set by WriteHeader.
//
// Note that if a Handler never calls WriteHeader or Write,
// this might end up being 0, rather than the implicit
// http.StatusOK. To get the implicit value, use the Result
// method.
Code int
// HeaderMap contains the headers explicitly set by the Handler.
// It is an internal detail.
//
// Deprecated: HeaderMap exists for historical compatibility
// and should not be used. To access the headers returned by a handler,
// use the Response.Header map as returned by the Result method.
HeaderMap http.Header
// Body is the buffer to which the Handler's Write calls are sent.
// If nil, the Writes are silently discarded.
Body *bytes.Buffer
// Flushed is whether the Handler called Flush.
Flushed bool
wroteHeader bool
}
// NewResourceResponseWriter returns an initialized ResponseWriter.
func NewResourceResponseWriter() *ResourceResponseWriter {
return &ResourceResponseWriter{
HeaderMap: make(http.Header),
Body: new(bytes.Buffer),
Code: 200,
}
}
// Header implements http.ResponseWriter. It returns the response
// headers to mutate within a handler. To test the headers that were
// written after a handler completes, use the Result method and see
// the returned Response value's Header.
func (rw *ResourceResponseWriter) Header() http.Header {
m := rw.HeaderMap
if m == nil {
m = make(http.Header)
rw.HeaderMap = m
}
return m
}
// writeHeader writes a header if it was not written yet and
// detects Content-Type if needed.
//
// bytes or str are the beginning of the response body.
// We pass both to avoid unnecessarily generate garbage
// in rw.WriteString which was created for performance reasons.
// Non-nil bytes win.
func (rw *ResourceResponseWriter) writeHeader(b []byte, str string) {
if rw.wroteHeader {
return
}
if len(str) > 512 {
str = str[:512]
}
m := rw.Header()
_, hasType := m["Content-Type"]
hasTE := m.Get("Transfer-Encoding") != ""
if !hasType && !hasTE {
if b == nil {
b = []byte(str)
}
m.Set("Content-Type", http.DetectContentType(b))
}
rw.WriteHeader(200)
}
// Write implements http.ResponseWriter. The data in buf is written to
// rw.Body, if not nil.
func (rw *ResourceResponseWriter) Write(buf []byte) (int, error) {
rw.writeHeader(buf, "")
if rw.Body != nil {
rw.Body.Write(buf)
}
return len(buf), nil
}
// WriteHeader implements http.ResponseWriter.
func (rw *ResourceResponseWriter) WriteHeader(code int) {
if rw.wroteHeader {
return
}
rw.Code = code
rw.wroteHeader = true
if rw.HeaderMap == nil {
rw.HeaderMap = make(http.Header)
}
}
// Flush implements http.Flusher.
func (rw *ResourceResponseWriter) Flush() {
if !rw.wroteHeader {
rw.WriteHeader(200)
}
}
// Result returns the response generated by the handler.
func (rw *ResourceResponseWriter) Result() *pluginv2.CallResource_Response {
res := &pluginv2.CallResource_Response{
Code: int32(rw.Code),
Headers: map[string]*pluginv2.CallResource_StringList{},
}
if rw.Body != nil {
res.Body = rw.Body.Bytes()
}
for key, values := range rw.Header().Clone() {
res.Headers[key] = &pluginv2.CallResource_StringList{
Values: values,
}
}
return res
}