Plugins: Core plugins register via backend factory provider (#43171)

* refactoring store interface and init flow

* fix import

* fix linter

* refactor resource calling

* load with class

* re-order args

* fix tests

* fix linter

* remove old creator

* add custom config struct

* fix some tests

* cleanup

* fix

* tackle plugins

* fix linter

* refactor and fix test

* add connect failure error

* add fix for azure, cloud monitoring and test data

* restructure

* remove unused err

* add fake tracer for test

* fix grafana ds plugin
This commit is contained in:
Will Browne
2022-01-20 18:16:22 +01:00
committed by GitHub
parent 2fd76ecaf7
commit 7fbc7d019a
30 changed files with 326 additions and 380 deletions
@@ -85,7 +85,7 @@ func writeResponse(rw http.ResponseWriter, code int, msg string) {
}
}
func (s *Service) resourceHandler(subDataSource string) func(rw http.ResponseWriter, req *http.Request) {
func (s *Service) handleResourceReq(subDataSource string) func(rw http.ResponseWriter, req *http.Request) {
return func(rw http.ResponseWriter, req *http.Request) {
azlog.Debug("Received resource call", "url", req.URL.String(), "method", req.Method)
@@ -115,11 +115,13 @@ func (s *Service) resourceHandler(subDataSource string) func(rw http.ResponseWri
}
}
// registerRoutes provides route definitions shared with the frontend.
// newResourceMux provides route definitions shared with the frontend.
// Check: /public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/common.ts <routeNames>
func (s *Service) registerRoutes(mux *http.ServeMux) {
mux.HandleFunc("/azuremonitor/", s.resourceHandler(azureMonitor))
mux.HandleFunc("/appinsights/", s.resourceHandler(appInsights))
mux.HandleFunc("/loganalytics/", s.resourceHandler(azureLogAnalytics))
mux.HandleFunc("/resourcegraph/", s.resourceHandler(azureResourceGraph))
func (s *Service) newResourceMux() *http.ServeMux {
mux := http.NewServeMux()
mux.HandleFunc("/azuremonitor/", s.handleResourceReq(azureMonitor))
mux.HandleFunc("/appinsights/", s.handleResourceReq(appInsights))
mux.HandleFunc("/loganalytics/", s.handleResourceReq(azureLogAnalytics))
mux.HandleFunc("/resourcegraph/", s.handleResourceReq(azureResourceGraph))
return mux
}
@@ -91,7 +91,7 @@ func (s *fakeProxy) Do(rw http.ResponseWriter, req *http.Request, cli *http.Clie
return nil
}
func Test_resourceHandler(t *testing.T) {
func Test_handleResourceReq(t *testing.T) {
proxy := &fakeProxy{}
s := Service{
im: &fakeInstance{
@@ -102,7 +102,6 @@ func Test_resourceHandler(t *testing.T) {
},
},
},
Cfg: &setting.Cfg{},
executors: map[string]azDatasourceExecutor{
azureMonitor: &AzureMonitorDatasource{
proxy: proxy,
@@ -114,7 +113,7 @@ func Test_resourceHandler(t *testing.T) {
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
s.resourceHandler(azureMonitor)(rw, req)
s.handleResourceReq(azureMonitor)(rw, req)
expectedURL := "https://management.azure.com/subscriptions/44693801"
if proxy.requestedURL != expectedURL {
t.Errorf("Unexpected result URL. Got %s, expecting %s", proxy.requestedURL, expectedURL)
+17 -20
View File
@@ -12,18 +12,16 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/azcredentials"
)
const (
timeSeries = "time_series"
pluginID = "grafana-azure-monitor-datasource"
)
var (
@@ -31,7 +29,7 @@ var (
legendKeyFormat = regexp.MustCompile(`\{\{\s*(.+?)\s*\}\}`)
)
func ProvideService(cfg *setting.Cfg, httpClientProvider *httpclient.Provider, pluginStore plugins.Store, tracer tracing.Tracer) *Service {
func ProvideService(cfg *setting.Cfg, httpClientProvider *httpclient.Provider, tracer tracing.Tracer) *Service {
proxy := &httpServiceProxy{}
executors := map[string]azDatasourceExecutor{
azureMonitor: &AzureMonitorDatasource{proxy: proxy},
@@ -43,37 +41,36 @@ func ProvideService(cfg *setting.Cfg, httpClientProvider *httpclient.Provider, p
im := datasource.NewInstanceManager(NewInstanceSettings(cfg, *httpClientProvider, executors))
s := &Service{
Cfg: cfg,
im: im,
executors: executors,
tracer: tracer,
}
mux := s.newMux()
resourceMux := http.NewServeMux()
s.registerRoutes(resourceMux)
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: mux,
CallResourceHandler: httpadapter.New(resourceMux),
})
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
if err := pluginStore.AddWithFactory(context.Background(), pluginID, factory, resolver); err != nil {
azlog.Error("Failed to register plugin", "error", err)
}
s.queryMux = s.newQueryMux()
s.resourceHandler = httpadapter.New(s.newResourceMux())
return s
}
func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
return s.queryMux.QueryData(ctx, req)
}
func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
return s.resourceHandler.CallResource(ctx, req, sender)
}
type serviceProxy interface {
Do(rw http.ResponseWriter, req *http.Request, cli *http.Client) http.ResponseWriter
}
type Service struct {
Cfg *setting.Cfg
im instancemgmt.InstanceManager
executors map[string]azDatasourceExecutor
tracer tracing.Tracer
queryMux *datasource.QueryTypeMux
resourceHandler backend.CallResourceHandler
tracer tracing.Tracer
}
type azureMonitorSettings struct {
@@ -182,7 +179,7 @@ func (s *Service) getDataSourceFromPluginReq(req *backend.QueryDataRequest) (dat
return dsInfo, nil
}
func (s *Service) newMux() *datasource.QueryTypeMux {
func (s *Service) newQueryMux() *datasource.QueryTypeMux {
mux := datasource.NewQueryTypeMux()
for dsType := range s.executors {
// Make a copy of the string to keep the reference after the iterator
+1 -6
View File
@@ -99,10 +99,6 @@ func (f *fakeExecutor) executeTimeSeriesQuery(ctx context.Context, originalQueri
}
func Test_newMux(t *testing.T) {
cfg := &setting.Cfg{
Azure: setting.AzureSettings{},
}
tests := []struct {
name string
queryType string
@@ -126,7 +122,6 @@ func Test_newMux(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &Service{
Cfg: cfg,
im: &fakeInstance{
routes: routes[azureMonitorPublic],
services: map[string]datasourceService{
@@ -144,7 +139,7 @@ func Test_newMux(t *testing.T) {
},
},
}
mux := s.newMux()
mux := s.newQueryMux()
res, err := mux.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{},
Queries: []backend.DataQuery{
+11 -25
View File
@@ -16,6 +16,7 @@ import (
"time"
"github.com/grafana/grafana-google-sdk-go/pkg/utils"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
@@ -25,10 +26,6 @@ import (
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/setting"
)
@@ -61,8 +58,6 @@ var (
)
const (
pluginID string = "stackdriver"
gceAuthentication string = "gce"
jwtAuthentication string = "jwt"
metricQueryType string = "metrics"
@@ -72,31 +67,22 @@ const (
perSeriesAlignerDefault string = "ALIGN_MEAN"
)
func ProvideService(cfg *setting.Cfg, httpClientProvider httpclient.Provider, pluginStore plugins.Store,
dsService *datasources.Service, tracer tracing.Tracer) *Service {
func ProvideService(httpClientProvider httpclient.Provider, tracer tracing.Tracer) *Service {
s := &Service{
httpClientProvider: httpClientProvider,
cfg: cfg,
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
dsService: dsService,
tracer: tracer,
httpClientProvider: httpClientProvider,
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
}
mux := http.NewServeMux()
s.registerRoutes(mux)
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: s,
CallResourceHandler: httpadapter.New(mux),
CheckHealthHandler: s,
})
s.resourceHandler = httpadapter.New(s.newResourceMux())
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
if err := pluginStore.AddWithFactory(context.Background(), pluginID, factory, resolver); err != nil {
slog.Error("Failed to register plugin", "error", err)
}
return s
}
func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
return s.resourceHandler.CallResource(ctx, req, sender)
}
func (s *Service) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
dsInfo, err := s.getDSInfo(req.PluginContext)
if err != nil {
@@ -138,10 +124,10 @@ func (s *Service) CheckHealth(ctx context.Context, req *backend.CheckHealthReque
type Service struct {
httpClientProvider httpclient.Provider
cfg *setting.Cfg
im instancemgmt.InstanceManager
dsService *datasources.Service
tracer tracing.Tracer
resourceHandler backend.CallResourceHandler
}
type QueryModel struct {
+8 -7
View File
@@ -25,13 +25,14 @@ const resourceManagerPath = "/v1/projects"
type processResponse func(body []byte) ([]json.RawMessage, string, error)
func (s *Service) registerRoutes(mux *http.ServeMux) {
func (s *Service) newResourceMux() *http.ServeMux {
mux := http.NewServeMux()
mux.HandleFunc("/gceDefaultProject", getGCEDefaultProject)
mux.HandleFunc("/metricDescriptors/", s.resourceHandler(cloudMonitor, processMetricDescriptors))
mux.HandleFunc("/services/", s.resourceHandler(cloudMonitor, processServices))
mux.HandleFunc("/slo-services/", s.resourceHandler(cloudMonitor, processSLOs))
mux.HandleFunc("/projects", s.resourceHandler(resourceManager, processProjects))
mux.HandleFunc("/metricDescriptors/", s.handleResourceReq(cloudMonitor, processMetricDescriptors))
mux.HandleFunc("/services/", s.handleResourceReq(cloudMonitor, processServices))
mux.HandleFunc("/slo-services/", s.handleResourceReq(cloudMonitor, processSLOs))
mux.HandleFunc("/projects", s.handleResourceReq(resourceManager, processProjects))
return mux
}
func getGCEDefaultProject(rw http.ResponseWriter, req *http.Request) {
@@ -43,7 +44,7 @@ func getGCEDefaultProject(rw http.ResponseWriter, req *http.Request) {
writeResponse(rw, http.StatusOK, project)
}
func (s *Service) resourceHandler(subDataSource string, responseFn processResponse) func(rw http.ResponseWriter, req *http.Request) {
func (s *Service) handleResourceReq(subDataSource string, responseFn processResponse) func(rw http.ResponseWriter, req *http.Request) {
return func(rw http.ResponseWriter, req *http.Request) {
client, code, err := s.setRequestVariables(req, subDataSource)
if err != nil {
+2 -15
View File
@@ -27,8 +27,6 @@ import (
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
)
@@ -56,29 +54,18 @@ const defaultRegion = "default"
const logIdentifierInternal = "__log__grafana_internal__"
const logStreamIdentifierInternal = "__logstream__grafana_internal__"
const pluginID = "cloudwatch"
var plog = log.New("tsdb.cloudwatch")
var aliasFormat = regexp.MustCompile(`\{\{\s*(.+?)\s*\}\}`)
func ProvideService(cfg *setting.Cfg, httpClientProvider httpclient.Provider, pluginStore plugins.Store) (*CloudWatchService, error) {
func ProvideService(cfg *setting.Cfg, httpClientProvider httpclient.Provider) *CloudWatchService {
plog.Debug("initing")
executor := newExecutor(datasource.NewInstanceManager(NewInstanceSettings(httpClientProvider)), cfg, awsds.NewSessionCache())
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: executor,
})
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
if err := pluginStore.AddWithFactory(context.Background(), pluginID, factory, resolver); err != nil {
plog.Error("Failed to register plugin", "error", err)
return nil, err
}
return &CloudWatchService{
Cfg: cfg,
Executor: executor,
}, nil
}
}
type CloudWatchService struct {
+5 -28
View File
@@ -12,47 +12,24 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
es "github.com/grafana/grafana/pkg/tsdb/elasticsearch/client"
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
)
var eslog = log.New("tsdb.elasticsearch")
const pluginID = "elasticsearch"
type Service struct {
HTTPClientProvider httpclient.Provider
httpClientProvider httpclient.Provider
intervalCalculator intervalv2.Calculator
im instancemgmt.InstanceManager
}
func ProvideService(cfg *setting.Cfg, httpClientProvider httpclient.Provider, pluginStore plugins.Store) (*Service, error) {
func ProvideService(httpClientProvider httpclient.Provider) *Service {
eslog.Debug("initializing")
im := datasource.NewInstanceManager(newInstanceSettings())
s := newService(im, httpClientProvider)
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: newService(im, s.HTTPClientProvider),
})
if err := pluginStore.AddWithFactory(context.Background(), pluginID, factory,
plugins.CoreDataSourcePathResolver(cfg, pluginID)); err != nil {
eslog.Error("Failed to register plugin", "error", err)
return nil, err
}
return s, nil
}
// newService creates a new executor func.
func newService(im instancemgmt.InstanceManager, httpClientProvider httpclient.Provider) *Service {
return &Service{
im: im,
HTTPClientProvider: httpClientProvider,
im: datasource.NewInstanceManager(newInstanceSettings()),
httpClientProvider: httpClientProvider,
intervalCalculator: intervalv2.NewCalculator(),
}
}
@@ -67,7 +44,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
return &backend.QueryDataResponse{}, err
}
client, err := es.NewClient(ctx, s.HTTPClientProvider, dsInfo, req.Queries[0].TimeRange)
client, err := es.NewClient(ctx, s.httpClientProvider, dsInfo, req.Queries[0].TimeRange)
if err != nil {
return &backend.QueryDataResponse{}, err
}
+3 -15
View File
@@ -14,8 +14,6 @@ import (
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/testdatasource"
)
@@ -32,8 +30,6 @@ const DatasourceID = -1
// Grafana DS command.
const DatasourceUID = "grafana"
const pluginID = "grafana"
// Make sure Service implements required interfaces.
// This is important to do since otherwise we will only get a
// not implemented error response from plugin at runtime.
@@ -43,11 +39,11 @@ var (
logger = log.New("tsdb.grafana")
)
func ProvideService(cfg *setting.Cfg, pluginStore plugins.Store) *Service {
return newService(cfg, pluginStore)
func ProvideService(cfg *setting.Cfg) *Service {
return newService(cfg)
}
func newService(cfg *setting.Cfg, pluginStore plugins.Store) *Service {
func newService(cfg *setting.Cfg) *Service {
s := &Service{
staticRootPath: cfg.StaticRootPath,
roots: []string{
@@ -59,14 +55,6 @@ func newService(cfg *setting.Cfg, pluginStore plugins.Store) *Service {
},
}
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
if err := pluginStore.AddWithFactory(context.Background(), pluginID, coreplugin.New(backend.ServeOpts{
CheckHealthHandler: s,
QueryDataHandler: s,
}), resolver); err != nil {
logger.Error("Failed to register plugin", "error", err)
return nil
}
return s
}
+2 -13
View File
@@ -1,13 +1,10 @@
package grafanads
import (
"context"
"encoding/json"
"path"
"testing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana-plugin-sdk-go/backend"
@@ -21,7 +18,7 @@ func asJSON(v interface{}) json.RawMessage {
}
func TestReadFolderListing(t *testing.T) {
ds := newService(&setting.Cfg{StaticRootPath: "../../../public"}, &fakePluginStore{})
ds := newService(&setting.Cfg{StaticRootPath: "../../../public"})
dr := ds.doListQuery(backend.DataQuery{
QueryType: "x",
JSON: asJSON(listQueryModel{
@@ -33,7 +30,7 @@ func TestReadFolderListing(t *testing.T) {
}
func TestReadCSVFile(t *testing.T) {
ds := newService(&setting.Cfg{StaticRootPath: "../../../public"}, &fakePluginStore{})
ds := newService(&setting.Cfg{StaticRootPath: "../../../public"})
dr := ds.doReadQuery(backend.DataQuery{
QueryType: "x",
JSON: asJSON(readQueryModel{
@@ -43,11 +40,3 @@ func TestReadCSVFile(t *testing.T) {
err := experimental.CheckGoldenDataResponse(path.Join("testdata", "jslib.golden.txt"), &dr, true)
require.NoError(t, err)
}
type fakePluginStore struct {
plugins.Store
}
func (ps *fakePluginStore) AddWithFactory(_ context.Context, _ string, _ backendplugin.PluginFactoryFunc, _ plugins.PluginPathResolver) error {
return nil
}
+2 -17
View File
@@ -26,8 +26,6 @@ import (
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/legacydata"
)
@@ -39,29 +37,16 @@ type Service struct {
}
const (
pluginID = "graphite"
TargetFullModelField = "targetFull"
TargetModelField = "target"
)
func ProvideService(cfg *setting.Cfg, httpClientProvider httpclient.Provider, pluginStore plugins.Store, tracer tracing.Tracer) (*Service, error) {
s := &Service{
func ProvideService(httpClientProvider httpclient.Provider, tracer tracing.Tracer) *Service {
return &Service{
logger: log.New("tsdb.graphite"),
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
tracer: tracer,
}
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: s,
})
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
if err := pluginStore.AddWithFactory(context.Background(), pluginID, factory, resolver); err != nil {
s.logger.Error("Failed to register plugin", "error", err)
return nil, err
}
return s, nil
}
type datasourceInfo struct {
+9 -26
View File
@@ -15,18 +15,14 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/influxdb/flux"
"github.com/grafana/grafana/pkg/tsdb/influxdb/models"
)
const pluginID = "influxdb"
type Service struct {
QueryParser *InfluxdbQueryParser
ResponseParser *ResponseParser
queryParser *InfluxdbQueryParser
responseParser *ResponseParser
glog log.Logger
im instancemgmt.InstanceManager
@@ -34,26 +30,13 @@ type Service struct {
var ErrInvalidHttpMode = errors.New("'httpMode' should be either 'GET' or 'POST'")
func ProvideService(cfg *setting.Cfg, httpClient httpclient.Provider, pluginStore plugins.Store) (*Service, error) {
im := datasource.NewInstanceManager(newInstanceSettings(httpClient))
s := &Service{
QueryParser: &InfluxdbQueryParser{},
ResponseParser: &ResponseParser{},
func ProvideService(httpClient httpclient.Provider) *Service {
return &Service{
queryParser: &InfluxdbQueryParser{},
responseParser: &ResponseParser{},
glog: log.New("tsdb.influxdb"),
im: im,
im: datasource.NewInstanceManager(newInstanceSettings(httpClient)),
}
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: s,
})
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
if err := pluginStore.AddWithFactory(context.Background(), pluginID, factory, resolver); err != nil {
s.glog.Error("Failed to register plugin", "error", err)
return nil, err
}
return s, nil
}
func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.InstanceFactoryFunc {
@@ -146,7 +129,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
return &backend.QueryDataResponse{}, fmt.Errorf("InfluxDB returned error status: %s", res.Status)
}
resp := s.ResponseParser.Parse(res.Body, query)
resp := s.responseParser.Parse(res.Body, query)
return resp, nil
}
@@ -162,7 +145,7 @@ func (s *Service) getQuery(dsInfo *models.DatasourceInfo, query *backend.QueryDa
q := query.Queries[0]
return s.QueryParser.Parse(q)
return s.queryParser.Parse(q)
}
func (s *Service) createRequest(ctx context.Context, dsInfo *models.DatasourceInfo, query string) (*http.Request, error) {
+2 -2
View File
@@ -20,8 +20,8 @@ func TestExecutor_createRequest(t *testing.T) {
}
query := "SELECT awesomeness FROM somewhere"
s := &Service{
QueryParser: &InfluxdbQueryParser{},
ResponseParser: &ResponseParser{},
queryParser: &InfluxdbQueryParser{},
responseParser: &ResponseParser{},
glog: log.New("test"),
}
+3 -21
View File
@@ -17,9 +17,6 @@ import (
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/loki/pkg/logcli/client"
"github.com/grafana/loki/pkg/loghttp"
"github.com/grafana/loki/pkg/logproto"
@@ -29,33 +26,18 @@ import (
"github.com/prometheus/common/model"
)
const pluginID = "loki"
type Service struct {
im instancemgmt.InstanceManager
plog log.Logger
tracer tracing.Tracer
}
func ProvideService(cfg *setting.Cfg, httpClientProvider httpclient.Provider, pluginStore plugins.Store, tracer tracing.Tracer) (*Service, error) {
im := datasource.NewInstanceManager(newInstanceSettings(httpClientProvider))
s := &Service{
im: im,
func ProvideService(httpClientProvider httpclient.Provider, tracer tracing.Tracer) *Service {
return &Service{
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
plog: log.New("tsdb.loki"),
tracer: tracer,
}
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: s,
})
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
if err := pluginStore.AddWithFactory(context.Background(), pluginID, factory, resolver); err != nil {
s.plog.Error("Failed to register plugin", "error", err)
return nil, err
}
return s, nil
}
var (
+2 -15
View File
@@ -17,8 +17,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/sqleng"
"github.com/grafana/grafana/pkg/util"
@@ -26,25 +24,14 @@ import (
var logger = log.New("tsdb.mssql")
const pluginID = "mssql"
type Service struct {
im instancemgmt.InstanceManager
}
func ProvideService(cfg *setting.Cfg, pluginStore plugins.Store) (*Service, error) {
s := &Service{
func ProvideService(cfg *setting.Cfg) *Service {
return &Service{
im: datasource.NewInstanceManager(newInstanceSettings(cfg)),
}
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: s,
})
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
if err := pluginStore.AddWithFactory(context.Background(), pluginID, factory, resolver); err != nil {
logger.Error("Failed to register plugin", "error", err)
}
return s, nil
}
func (s *Service) getDataSourceHandler(pluginCtx backend.PluginContext) (*sqleng.DataSourceHandler, error) {
+2 -14
View File
@@ -20,14 +20,11 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/sqleng"
)
const (
pluginID = "mysql"
dateFormat = "2006-01-02"
dateTimeFormat1 = "2006-01-02 15:04:05"
dateTimeFormat2 = "2006-01-02T15:04:05Z"
@@ -44,19 +41,10 @@ func characterEscape(s string, escapeChar string) string {
return strings.ReplaceAll(s, escapeChar, url.QueryEscape(escapeChar))
}
func ProvideService(cfg *setting.Cfg, pluginStore plugins.Store, httpClientProvider httpclient.Provider) (*Service, error) {
s := &Service{
func ProvideService(cfg *setting.Cfg, httpClientProvider httpclient.Provider) *Service {
return &Service{
im: datasource.NewInstanceManager(newInstanceSettings(cfg, httpClientProvider)),
}
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: s,
})
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
if err := pluginStore.AddWithFactory(context.Background(), pluginID, factory, resolver); err != nil {
logger.Error("Failed to register plugin", "error", err)
}
return s, nil
}
func newInstanceSettings(cfg *setting.Cfg, httpClientProvider httpclient.Provider) datasource.InstanceFactoryFunc {
+3 -18
View File
@@ -19,35 +19,20 @@ import (
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
"golang.org/x/net/context/ctxhttp"
)
const pluginID = "opentsdb"
type Service struct {
logger log.Logger
im instancemgmt.InstanceManager
}
func ProvideService(cfg *setting.Cfg, httpClientProvider httpclient.Provider, pluginStore plugins.Store) (*Service, error) {
im := datasource.NewInstanceManager(newInstanceSettings(httpClientProvider))
s := &Service{
func ProvideService(httpClientProvider httpclient.Provider) *Service {
return &Service{
logger: log.New("tsdb.opentsdb"),
im: im,
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
}
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: s,
})
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
if err := pluginStore.AddWithFactory(context.Background(), pluginID, factory, resolver); err != nil {
return nil, err
}
return s, nil
}
type datasourceInfo struct {
+2 -14
View File
@@ -14,8 +14,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/sqleng"
"github.com/grafana/grafana/pkg/util/errutil"
@@ -23,22 +21,12 @@ import (
var logger = log.New("tsdb.postgres")
const pluginID = "postgres"
func ProvideService(cfg *setting.Cfg, pluginStore plugins.Store) (*Service, error) {
func ProvideService(cfg *setting.Cfg) *Service {
s := &Service{
tlsManager: newTLSManager(logger, cfg.DataPath),
}
s.im = datasource.NewInstanceManager(s.newInstanceSettings(cfg))
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: s,
})
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
if err := pluginStore.AddWithFactory(context.Background(), pluginID, factory, resolver); err != nil {
logger.Error("Failed to register plugin", "error", err)
}
return s, nil
return s
}
type Service struct {
+3 -21
View File
@@ -15,9 +15,6 @@ import (
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
apiv1 "github.com/prometheus/client_golang/api/prometheus/v1"
)
@@ -28,34 +25,19 @@ var (
safeRes = 11000
)
const pluginID = "prometheus"
type Service struct {
intervalCalculator intervalv2.Calculator
im instancemgmt.InstanceManager
tracer tracing.Tracer
}
func ProvideService(cfg *setting.Cfg, httpClientProvider httpclient.Provider, pluginStore plugins.Store, tracer tracing.Tracer) (*Service, error) {
func ProvideService(httpClientProvider httpclient.Provider, tracer tracing.Tracer) *Service {
plog.Debug("initializing")
im := datasource.NewInstanceManager(newInstanceSettings(httpClientProvider))
s := &Service{
return &Service{
intervalCalculator: intervalv2.NewCalculator(),
im: im,
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
tracer: tracer,
}
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: s,
})
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
if err := pluginStore.AddWithFactory(context.Background(), pluginID, factory, resolver); err != nil {
plog.Error("Failed to register plugin", "error", err)
return nil, err
}
return s, nil
}
func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.InstanceFactoryFunc {
+3 -22
View File
@@ -13,38 +13,19 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
"go.opentelemetry.io/collector/model/otlp"
)
const pluginID = "tempo"
type Service struct {
im instancemgmt.InstanceManager
tlog log.Logger
}
func ProvideService(cfg *setting.Cfg, httpClientProvider httpclient.Provider, pluginStore plugins.Store) (*Service, error) {
im := datasource.NewInstanceManager(newInstanceSettings(httpClientProvider))
s := &Service{
func ProvideService(httpClientProvider httpclient.Provider) *Service {
return &Service{
tlog: log.New("tsdb.tempo"),
im: im,
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
}
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: s,
})
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
if err := pluginStore.AddWithFactory(context.Background(), pluginID, factory, resolver); err != nil {
s.tlog.Error("Failed to register plugin", "error", err)
return nil, err
}
return s, nil
}
type datasourceInfo struct {
+3 -1
View File
@@ -15,13 +15,15 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter"
)
func (s *Service) RegisterRoutes(mux *http.ServeMux) {
func (s *Service) registerRoutes() *http.ServeMux {
mux := http.NewServeMux()
mux.HandleFunc("/", s.testGetHandler)
mux.HandleFunc("/scenarios", s.getScenariosHandler)
mux.HandleFunc("/stream", s.testStreamHandler)
mux.Handle("/test", createJSONHandler(s.logger))
mux.Handle("/test/json", createJSONHandler(s.logger))
mux.HandleFunc("/boom", s.testPanicHandler)
return mux
}
func (s *Service) testGetHandler(rw http.ResponseWriter, req *http.Request) {
+19 -27
View File
@@ -2,22 +2,18 @@ package testdatasource
import (
"context"
"net/http"
"time"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/setting"
)
const pluginID = "testdata"
func ProvideService(cfg *setting.Cfg, pluginStore plugins.Store) (*Service, error) {
func ProvideService(cfg *setting.Cfg) *Service {
s := &Service{
queryMux: datasource.NewQueryTypeMux(),
scenarios: map[string]*Scenario{},
@@ -37,29 +33,25 @@ func ProvideService(cfg *setting.Cfg, pluginStore plugins.Store) (*Service, erro
}
s.registerScenarios()
s.resourceHandler = httpadapter.New(s.registerRoutes())
rMux := http.NewServeMux()
s.RegisterRoutes(rMux)
factory := coreplugin.New(backend.ServeOpts{
QueryDataHandler: s.queryMux,
CallResourceHandler: httpadapter.New(rMux),
StreamHandler: s,
})
resolver := plugins.CoreDataSourcePathResolver(cfg, pluginID)
err := pluginStore.AddWithFactory(context.Background(), pluginID, factory, resolver)
if err != nil {
return nil, err
}
return s, nil
return s
}
type Service struct {
cfg *setting.Cfg
logger log.Logger
scenarios map[string]*Scenario
frame *data.Frame
labelFrame *data.Frame
queryMux *datasource.QueryTypeMux
cfg *setting.Cfg
logger log.Logger
scenarios map[string]*Scenario
frame *data.Frame
labelFrame *data.Frame
queryMux *datasource.QueryTypeMux
resourceHandler backend.CallResourceHandler
}
func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
return s.queryMux.QueryData(ctx, req)
}
func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
return s.resourceHandler.CallResource(ctx, req, sender)
}