Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alternatives for serving plugin #99

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
85 changes: 85 additions & 0 deletions backend/datasource/datasource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package datasource
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Package datasource ....


import (
"context"

"github.com/grafana/grafana-plugin-sdk-go/backend"
)

// CheckDataSourceHealthRequest contains the healthcheck request
type CheckDataSourceHealthRequest struct {
pluginConfig backend.PluginConfig
OrgID int64
DataSourceConfig backend.DataSourceConfig
}

// CheckDataSourceHealthHandler enables users to send health check
// requests to a data source plugin.
type CheckDataSourceHealthHandler interface {
CheckDataSourceHealth(ctx context.Context, req *CheckDataSourceHealthRequest) (*backend.CheckHealthResult, error)
}

type CheckDataSourceHealthHandlerFunc func(ctx context.Context, req *CheckDataSourceHealthRequest) (*backend.CheckHealthResult, error)

func (fn CheckDataSourceHealthHandlerFunc) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
return fn(ctx, &CheckDataSourceHealthRequest{
pluginConfig: req.PluginConfig,
OrgID: req.PluginConfig.OrgID,
DataSourceConfig: *(req.PluginConfig.DataSourceConfig),
})
}

type CallDataSourceResourceRequest struct {
pluginConfig backend.PluginConfig
OrgID int64
DataSourceConfig backend.DataSourceConfig
Comment on lines +34 to +35
Copy link
Member Author

@marefr marefr Apr 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only OrgID and DataSourceConfig exposed here compared to regular CallResourceRequest which includes both PluginConfig and DataSourceConfig.

Helps not confusing plugin developer to use PluginConfig (currently only app plugins) when should be using DataSourceConfig.

Path string
Method string
URL string
Headers map[string][]string
Body []byte
User *backend.User
}

// CallDataSourceResourceHandler handles resource calls.
type CallDataSourceResourceHandler interface {
CallDataSourceResource(ctx context.Context, req *CallDataSourceResourceRequest, sender backend.CallResourceResponseSender) error
}

type CallDataSourceResourceHandlerFunc func(ctx context.Context, req *CallDataSourceResourceRequest, sender backend.CallResourceResponseSender) error

func (fn CallDataSourceResourceHandlerFunc) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
return fn(ctx, &CallDataSourceResourceRequest{
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not super found of this mapping back and forth, but removes the need of implementing yet another interface in resource and httpadapter packages.

pluginConfig: req.PluginConfig,
OrgID: req.PluginConfig.OrgID,
DataSourceConfig: *(req.PluginConfig.DataSourceConfig),
User: req.User,
Path: req.Path,
URL: req.URL,
Method: req.Method,
Headers: req.Headers,
Body: req.Body,
}, sender)
}

func NewCheckDataSourceHealthHandlerFunc(h backend.CheckHealthHandler) CheckDataSourceHealthHandlerFunc {
return func(ctx context.Context, req *CheckDataSourceHealthRequest) (*backend.CheckHealthResult, error) {
return h.CheckHealth(ctx, &backend.CheckHealthRequest{
PluginConfig: req.pluginConfig,
})
}
}

func NewCallDataSourceResourceHandlerFunc(h backend.CallResourceHandler) CallDataSourceResourceHandlerFunc {
return func(ctx context.Context, req *CallDataSourceResourceRequest, sender backend.CallResourceResponseSender) error {
return h.CallResource(ctx, &backend.CallResourceRequest{
PluginConfig: req.pluginConfig,
User: req.User,
Path: req.Path,
URL: req.URL,
Method: req.Method,
Headers: req.Headers,
Body: req.Body,
}, sender)
}
}
25 changes: 25 additions & 0 deletions backend/datasource/serve.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package datasource

import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
)

type Plugin interface {
CheckDataSourceHealthHandler
CallDataSourceResourceHandler
backend.QueryDataHandler
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be correct, this one should probably have a new interface in this package as well to only include DataSourceConfig in request and not PluginConfig.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be an interface similar to https://github.com/grafana/grafana/blob/master/pkg/tsdb/query_endpoint.go#L11, basically using similar DataSource model struct.

}

type PluginFactoryFunc func(logger log.Logger, c backend.ConfigurePlugin) Plugin

func Serve(fn PluginFactoryFunc) {
backend.Serve(func(logger log.Logger, c backend.ConfigurePlugin) backend.ServeOpts {
ds := fn(logger, c)
return backend.ServeOpts{
CheckHealthHandler: CheckDataSourceHealthHandlerFunc(ds.CheckDataSourceHealth),
CallResourceHandler: CallDataSourceResourceHandlerFunc(ds.CallDataSourceResource),
QueryDataHandler: ds,
}
})
}
2 changes: 2 additions & 0 deletions backend/diagnostics/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package diagnostics provides support for handling health checks.
package diagnostics
21 changes: 21 additions & 0 deletions backend/diagnostics/health_ok_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package diagnostics

import (
"context"

"github.com/grafana/grafana-plugin-sdk-go/backend"
)

type okHandler struct {
}

func (h *okHandler) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
return &backend.CheckHealthResult{
Status: backend.HealthStatusOk,
}, nil
}

// OKCheckHealthHandler check health handler that returns backend.HealthStatusOk status.
func OKCheckHealthHandler() backend.CheckHealthHandler {
return &okHandler{}
}
4 changes: 1 addition & 3 deletions backend/grpcplugin/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type ServeOpts struct {
}

// Serve starts serving the plugin over gRPC.
func Serve(opts ServeOpts) error {
func Serve(opts ServeOpts) {
versionedPlugins := make(map[int]plugin.PluginSet)
pSet := make(plugin.PluginSet)

Expand Down Expand Up @@ -57,6 +57,4 @@ func Serve(opts ServeOpts) error {
VersionedPlugins: versionedPlugins,
GRPCServer: opts.GRPCServer,
})

return nil
}
2 changes: 2 additions & 0 deletions backend/resource/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package resource provides support for handling resource calls.
package resource
22 changes: 22 additions & 0 deletions backend/resource/not_found_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package resource

import (
"context"
"net/http"

"github.com/grafana/grafana-plugin-sdk-go/backend"
)

type notFoundHandler struct {
}

func (h *notFoundHandler) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
return sender.Send(&backend.CallResourceResponse{
Status: http.StatusNotFound,
})
}

// NotFoundHandler call resource handler that returns HTTP 404 status code.
func NotFoundHandler() backend.CallResourceHandler {
return &notFoundHandler{}
}
111 changes: 109 additions & 2 deletions backend/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package backend

import (
"github.com/grafana/grafana-plugin-sdk-go/backend/grpcplugin"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/prometheus/client_golang/prometheus"
)

Expand All @@ -13,8 +14,20 @@ type ServeOpts struct {
TransformDataHandler TransformDataHandler
}

type ConfigurePlugin struct {
Metrics prometheus.Registerer
}

type ServePluginFunc func(logger log.Logger, c ConfigurePlugin) ServeOpts

// Serve starts serving the plugin over gRPC.
func Serve(opts ServeOpts) error {
func Serve(fn ServePluginFunc) {
logger := log.New()
c := ConfigurePlugin{
Metrics: prometheus.DefaultRegisterer,
}
opts := fn(logger, c)

pluginOpts := grpcplugin.ServeOpts{
DiagnosticsServer: newDiagnosticsSDKAdapter(prometheus.DefaultGatherer, opts.CheckHealthHandler),
}
Expand All @@ -31,5 +44,99 @@ func Serve(opts ServeOpts) error {
pluginOpts.TransformServer = newTransformSDKAdapter(opts.TransformDataHandler)
}

return grpcplugin.Serve(pluginOpts)
grpcplugin.Serve(pluginOpts)
}

type Plugin interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments please for these exported interfaces and the types that Follow

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah good point, but still a draft. So only consider the concept/examples

CheckHealthHandler
CallResourceHandler
}

type DataSourcePlugin interface {
Plugin
QueryDataHandler
}

type TransformPlugin interface {
TransformDataHandler
}

type PluginFactoryFunc func(logger log.Logger, c ConfigurePlugin) Plugin
type DataSourcePluginFactoryFunc func(logger log.Logger, c ConfigurePlugin) DataSourcePlugin
type TransformPluginFactoryFunc func(logger log.Logger, c ConfigurePlugin) TransformPlugin

//ServePluginOpts options for serving plugins.
type ServePluginOpts struct {
PluginProvider PluginFactoryFunc
DataSourcePluginProvider DataSourcePluginFactoryFunc
TransformPluginProvider TransformPluginFactoryFunc
}

func ServePluginExample(opts ServePluginOpts) {
logger := log.New()
c := ConfigurePlugin{
Metrics: prometheus.DefaultRegisterer,
}

if opts.PluginProvider != nil {
p := opts.PluginProvider(logger, c)
grpcplugin.Serve(grpcplugin.ServeOpts{
DiagnosticsServer: newDiagnosticsSDKAdapter(prometheus.DefaultGatherer, p),
ResourceServer: newResourceSDKAdapter(p),
})
return
}

if opts.DataSourcePluginProvider != nil {
p := opts.DataSourcePluginProvider(logger, c)
grpcplugin.Serve(grpcplugin.ServeOpts{
DiagnosticsServer: newDiagnosticsSDKAdapter(prometheus.DefaultGatherer, p),
ResourceServer: newResourceSDKAdapter(p),
DataServer: newDataSDKAdapter(p),
})
return
}

if opts.TransformPluginProvider != nil {
p := opts.TransformPluginProvider(logger, c)
grpcplugin.Serve(grpcplugin.ServeOpts{
TransformServer: newTransformSDKAdapter(p),
})
return
}

panic("invalid arguments for serve plugin")
}

// ServePlugin starts serving the plugin over gRPC.
func ServePlugin(factory PluginFactoryFunc) {
if factory == nil {
panic("factory func cannot be nil")
}

ServePluginExample(ServePluginOpts{
PluginProvider: factory,
})
}

// ServeDataSourcePlugin starts serving the data source plugin over gRPC.
func ServeDataSourcePlugin(factory DataSourcePluginFactoryFunc) {
if factory == nil {
panic("factory func cannot be nil")
}

ServePluginExample(ServePluginOpts{
DataSourcePluginProvider: factory,
})
}

// ServeTransformPlugin starts serving the plugin over gRPC.
func ServeTransformPlugin(factory TransformPluginFactoryFunc) {
if factory == nil {
panic("factory func cannot be nil")
}

ServePluginExample(ServePluginOpts{
TransformPluginProvider: factory,
})
}
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,16 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0 h1:miYCvYqFXtl/J9FIy8eNpBfYthAEFg+Ys0XyUVEcDsc=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.5.0 h1:Ctq0iGpCmr3jeP77kbF2UxgvRwzWWz+4Bh9/vJTyg1A=
github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0 h1:ElTg5tNp4DqfV7UQjDqv2+RJlNzsDtvNAWccbItceIE=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
Expand Down