mirror of https://github.com/grafana/grafana.git
				
				
				
			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:
		
							parent
							
								
									2fd76ecaf7
								
							
						
					
					
						commit
						7fbc7d019a
					
				|  | @ -0,0 +1,100 @@ | |||
| package coreplugin | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/grafana/grafana-plugin-sdk-go/backend" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/plugins/backendplugin" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/azuremonitor" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/cloudmonitoring" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/cloudwatch" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/elasticsearch" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/grafanads" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/graphite" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/influxdb" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/loki" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/mssql" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/mysql" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/opentsdb" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/postgres" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/prometheus" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/tempo" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/testdatasource" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	CloudWatch      = "cloudwatch" | ||||
| 	CloudMonitoring = "stackdriver" | ||||
| 	AzureMonitor    = "grafana-azure-monitor-datasource" | ||||
| 	Elasticsearch   = "elasticsearch" | ||||
| 	Graphite        = "graphite" | ||||
| 	InfluxDB        = "influxdb" | ||||
| 	Loki            = "loki" | ||||
| 	OpenTSDB        = "opentsdb" | ||||
| 	Prometheus      = "prometheus" | ||||
| 	Tempo           = "tempo" | ||||
| 	TestData        = "testdata" | ||||
| 	PostgreSQL      = "postgres" | ||||
| 	MySQL           = "mysql" | ||||
| 	MSSQL           = "mssql" | ||||
| 	Grafana         = "grafana" | ||||
| ) | ||||
| 
 | ||||
| type Registry struct { | ||||
| 	store map[string]backendplugin.PluginFactoryFunc | ||||
| } | ||||
| 
 | ||||
| func NewRegistry(store map[string]backendplugin.PluginFactoryFunc) *Registry { | ||||
| 	return &Registry{ | ||||
| 		store: store, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func ProvideCoreRegistry(am *azuremonitor.Service, cw *cloudwatch.CloudWatchService, cm *cloudmonitoring.Service, | ||||
| 	es *elasticsearch.Service, grap *graphite.Service, idb *influxdb.Service, lk *loki.Service, otsdb *opentsdb.Service, | ||||
| 	pr *prometheus.Service, t *tempo.Service, td *testdatasource.Service, pg *postgres.Service, my *mysql.Service, | ||||
| 	ms *mssql.Service, graf *grafanads.Service) *Registry { | ||||
| 	return NewRegistry(map[string]backendplugin.PluginFactoryFunc{ | ||||
| 		CloudWatch:      asBackendPlugin(cw.Executor), | ||||
| 		CloudMonitoring: asBackendPlugin(cm), | ||||
| 		AzureMonitor:    asBackendPlugin(am), | ||||
| 		Elasticsearch:   asBackendPlugin(es), | ||||
| 		Graphite:        asBackendPlugin(grap), | ||||
| 		InfluxDB:        asBackendPlugin(idb), | ||||
| 		Loki:            asBackendPlugin(lk), | ||||
| 		OpenTSDB:        asBackendPlugin(otsdb), | ||||
| 		Prometheus:      asBackendPlugin(pr), | ||||
| 		Tempo:           asBackendPlugin(t), | ||||
| 		TestData:        asBackendPlugin(td), | ||||
| 		PostgreSQL:      asBackendPlugin(pg), | ||||
| 		MySQL:           asBackendPlugin(my), | ||||
| 		MSSQL:           asBackendPlugin(ms), | ||||
| 		Grafana:         asBackendPlugin(graf), | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (cr *Registry) Get(pluginID string) backendplugin.PluginFactoryFunc { | ||||
| 	return cr.store[pluginID] | ||||
| } | ||||
| 
 | ||||
| func asBackendPlugin(svc interface{}) backendplugin.PluginFactoryFunc { | ||||
| 	opts := backend.ServeOpts{} | ||||
| 	if queryHandler, ok := svc.(backend.QueryDataHandler); ok { | ||||
| 		opts.QueryDataHandler = queryHandler | ||||
| 	} | ||||
| 	if resourceHandler, ok := svc.(backend.CallResourceHandler); ok { | ||||
| 		opts.CallResourceHandler = resourceHandler | ||||
| 	} | ||||
| 	if streamHandler, ok := svc.(backend.StreamHandler); ok { | ||||
| 		opts.StreamHandler = streamHandler | ||||
| 	} | ||||
| 	if healthHandler, ok := svc.(backend.CheckHealthHandler); ok { | ||||
| 		opts.CheckHealthHandler = healthHandler | ||||
| 	} | ||||
| 
 | ||||
| 	if opts.QueryDataHandler != nil || opts.CallResourceHandler != nil || | ||||
| 		opts.CheckHealthHandler != nil || opts.StreamHandler != nil { | ||||
| 		return New(opts) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
|  | @ -7,18 +7,23 @@ import ( | |||
| 	"github.com/grafana/grafana/pkg/infra/log" | ||||
| 	"github.com/grafana/grafana/pkg/plugins" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/backendplugin" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/backendplugin/grpcplugin" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/backendplugin/pluginextensionv2" | ||||
| ) | ||||
| 
 | ||||
| type Service struct{} | ||||
| 
 | ||||
| func ProvideService() *Service { | ||||
| 	return &Service{} | ||||
| type Service struct { | ||||
| 	coreRegistry *coreplugin.Registry | ||||
| } | ||||
| 
 | ||||
| func (*Service) BackendFactory(ctx context.Context, p *plugins.Plugin) backendplugin.PluginFactoryFunc { | ||||
| 	for _, provider := range []PluginBackendProvider{RendererProvider, DefaultProvider} { | ||||
| func ProvideService(coreRegistry *coreplugin.Registry) *Service { | ||||
| 	return &Service{ | ||||
| 		coreRegistry: coreRegistry, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *Service) BackendFactory(ctx context.Context, p *plugins.Plugin) backendplugin.PluginFactoryFunc { | ||||
| 	for _, provider := range []PluginBackendProvider{CorePluginProvider(ctx, s.coreRegistry), RendererProvider, DefaultProvider} { | ||||
| 		if factory := provider(ctx, p); factory != nil { | ||||
| 			return factory | ||||
| 		} | ||||
|  | @ -43,6 +48,17 @@ var RendererProvider PluginBackendProvider = func(_ context.Context, p *plugins. | |||
| } | ||||
| 
 | ||||
| var DefaultProvider PluginBackendProvider = func(_ context.Context, p *plugins.Plugin) backendplugin.PluginFactoryFunc { | ||||
| 	// TODO check for executable
 | ||||
| 	cmd := plugins.ComposePluginStartCommand(p.Executable) | ||||
| 	return grpcplugin.NewBackendPlugin(p.ID, filepath.Join(p.PluginDir, cmd)) | ||||
| } | ||||
| 
 | ||||
| var CorePluginProvider = func(ctx context.Context, registry *coreplugin.Registry) PluginBackendProvider { | ||||
| 	return func(_ context.Context, p *plugins.Plugin) backendplugin.PluginFactoryFunc { | ||||
| 		if !p.IsCorePlugin() { | ||||
| 			return nil | ||||
| 		} | ||||
| 
 | ||||
| 		return registry.Get(p.ID) | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -15,6 +15,8 @@ import ( | |||
| 	"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" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/backendplugin/provider" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/manager/loader/finder" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/manager/loader/initializer" | ||||
|  | @ -904,7 +906,7 @@ func newLoader(cfg *plugins.Cfg) *Loader { | |||
| 	return &Loader{ | ||||
| 		cfg:                cfg, | ||||
| 		pluginFinder:       finder.New(), | ||||
| 		pluginInitializer:  initializer.New(cfg, &provider.Service{}, &fakeLicensingService{}), | ||||
| 		pluginInitializer:  initializer.New(cfg, provider.ProvideService(coreplugin.NewRegistry(make(map[string]backendplugin.PluginFactoryFunc))), &fakeLicensingService{}), | ||||
| 		signatureValidator: signature.NewValidator(&signature.UnsignedPluginAuthorizer{Cfg: cfg}), | ||||
| 		errs:               make(map[string]*plugins.SignatureError), | ||||
| 		log:                &fakeLogger{}, | ||||
|  |  | |||
|  | @ -471,17 +471,10 @@ func (m *PluginManager) shutdown(ctx context.Context) { | |||
| 
 | ||||
| // corePluginPaths provides a list of the Core plugin paths which need to be scanned on init()
 | ||||
| func corePluginPaths(cfg *setting.Cfg) []string { | ||||
| 	datasourcePaths := []string{ | ||||
| 		filepath.Join(cfg.StaticRootPath, "app/plugins/datasource/alertmanager"), | ||||
| 		filepath.Join(cfg.StaticRootPath, "app/plugins/datasource/dashboard"), | ||||
| 		filepath.Join(cfg.StaticRootPath, "app/plugins/datasource/jaeger"), | ||||
| 		filepath.Join(cfg.StaticRootPath, "app/plugins/datasource/mixed"), | ||||
| 		filepath.Join(cfg.StaticRootPath, "app/plugins/datasource/zipkin"), | ||||
| 	} | ||||
| 
 | ||||
| 	datasourcePaths := filepath.Join(cfg.StaticRootPath, "app/plugins/datasource") | ||||
| 	panelsPath := filepath.Join(cfg.StaticRootPath, "app/plugins/panel") | ||||
| 
 | ||||
| 	return append(datasourcePaths, panelsPath) | ||||
| 	return []string{datasourcePaths, panelsPath} | ||||
| } | ||||
| 
 | ||||
| // pluginSettingPaths provides a plugin paths defined in cfg.PluginSettings which need to be scanned on init()
 | ||||
|  |  | |||
|  | @ -2,16 +2,38 @@ package manager | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"net/http" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/infra/tracing" | ||||
| 	"go.opentelemetry.io/otel/trace" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/plugins" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/backendplugin/provider" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/manager/loader" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/manager/signature" | ||||
| 	"github.com/grafana/grafana/pkg/services/licensing" | ||||
| 	"github.com/grafana/grafana/pkg/setting" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/azuremonitor" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/cloudmonitoring" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/cloudwatch" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/elasticsearch" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/grafanads" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/graphite" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/influxdb" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/loki" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/mssql" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/mysql" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/opentsdb" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/postgres" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/prometheus" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/tempo" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/testdatasource" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/require" | ||||
|  | @ -40,13 +62,34 @@ func TestPluginManager_int_init(t *testing.T) { | |||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	tracer := &fakeTracer{} | ||||
| 
 | ||||
| 	license := &licensing.OSSLicensingService{ | ||||
| 		Cfg: cfg, | ||||
| 	} | ||||
| 
 | ||||
| 	hcp := httpclient.NewProvider() | ||||
| 	am := azuremonitor.ProvideService(cfg, hcp, tracer) | ||||
| 	cw := cloudwatch.ProvideService(cfg, hcp) | ||||
| 	cm := cloudmonitoring.ProvideService(hcp, tracer) | ||||
| 	es := elasticsearch.ProvideService(hcp) | ||||
| 	grap := graphite.ProvideService(hcp, tracer) | ||||
| 	idb := influxdb.ProvideService(hcp) | ||||
| 	lk := loki.ProvideService(hcp, tracer) | ||||
| 	otsdb := opentsdb.ProvideService(hcp) | ||||
| 	pr := prometheus.ProvideService(hcp, tracer) | ||||
| 	tmpo := tempo.ProvideService(hcp) | ||||
| 	td := testdatasource.ProvideService(cfg) | ||||
| 	pg := postgres.ProvideService(cfg) | ||||
| 	my := mysql.ProvideService(cfg, hcp) | ||||
| 	ms := mssql.ProvideService(cfg) | ||||
| 	graf := grafanads.ProvideService(cfg) | ||||
| 
 | ||||
| 	coreRegistry := coreplugin.ProvideCoreRegistry(am, cw, cm, es, grap, idb, lk, otsdb, pr, tmpo, td, pg, my, ms, graf) | ||||
| 
 | ||||
| 	pmCfg := plugins.FromGrafanaCfg(cfg) | ||||
| 	pm, err := ProvideService(cfg, nil, loader.New(pmCfg, license, | ||||
| 		&signature.UnsignedPluginAuthorizer{Cfg: pmCfg}, &provider.Service{}), nil) | ||||
| 		&signature.UnsignedPluginAuthorizer{Cfg: pmCfg}, provider.ProvideService(coreRegistry)), nil) | ||||
| 	require.NoError(t, err) | ||||
| 
 | ||||
| 	verifyCorePluginCatalogue(t, pm) | ||||
|  | @ -92,12 +135,27 @@ func verifyCorePluginCatalogue(t *testing.T, pm *PluginManager) { | |||
| 	} | ||||
| 
 | ||||
| 	expDataSources := map[string]struct{}{ | ||||
| 		"alertmanager": {}, | ||||
| 		"dashboard":    {}, | ||||
| 		"input":        {}, | ||||
| 		"jaeger":       {}, | ||||
| 		"mixed":        {}, | ||||
| 		"zipkin":       {}, | ||||
| 		"cloudwatch":                       {}, | ||||
| 		"stackdriver":                      {}, | ||||
| 		"grafana-azure-monitor-datasource": {}, | ||||
| 		"elasticsearch":                    {}, | ||||
| 		"graphite":                         {}, | ||||
| 		"influxdb":                         {}, | ||||
| 		"loki":                             {}, | ||||
| 		"opentsdb":                         {}, | ||||
| 		"prometheus":                       {}, | ||||
| 		"tempo":                            {}, | ||||
| 		"testdata":                         {}, | ||||
| 		"postgres":                         {}, | ||||
| 		"mysql":                            {}, | ||||
| 		"mssql":                            {}, | ||||
| 		"grafana":                          {}, | ||||
| 		"alertmanager":                     {}, | ||||
| 		"dashboard":                        {}, | ||||
| 		"input":                            {}, | ||||
| 		"jaeger":                           {}, | ||||
| 		"mixed":                            {}, | ||||
| 		"zipkin":                           {}, | ||||
| 	} | ||||
| 
 | ||||
| 	expApps := map[string]struct{}{ | ||||
|  | @ -177,3 +235,19 @@ func verifyPluginStaticRoutes(t *testing.T, pm *PluginManager) { | |||
| 	assert.Contains(t, routes, "test-app") | ||||
| 	assert.Equal(t, routes["test-app"].Directory, testAppPlugin.PluginDir) | ||||
| } | ||||
| 
 | ||||
| type fakeTracer struct { | ||||
| 	tracing.Tracer | ||||
| } | ||||
| 
 | ||||
| func (ft *fakeTracer) Run(context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (ft *fakeTracer) Start(ctx context.Context, _ string, _ ...trace.SpanStartOption) (context.Context, tracing.Span) { | ||||
| 	return ctx, nil | ||||
| } | ||||
| 
 | ||||
| func (ft *fakeTracer) Inject(context.Context, http.Header, tracing.Span) { | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -23,21 +23,6 @@ import ( | |||
| 	secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" | ||||
| 	"github.com/grafana/grafana/pkg/services/serviceaccounts" | ||||
| 	"github.com/grafana/grafana/pkg/services/updatechecker" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/azuremonitor" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/cloudmonitoring" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/cloudwatch" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/elasticsearch" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/grafanads" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/graphite" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/influxdb" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/loki" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/mssql" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/mysql" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/opentsdb" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/postgres" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/prometheus" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/tempo" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/testdatasource" | ||||
| ) | ||||
| 
 | ||||
| func ProvideBackgroundServiceRegistry( | ||||
|  | @ -48,11 +33,8 @@ func ProvideBackgroundServiceRegistry( | |||
| 	metrics *metrics.InternalMetricsService, usageStats *uss.UsageStats, updateChecker *updatechecker.Service, | ||||
| 	tracing tracing.Tracer, remoteCache *remotecache.RemoteCache, secretsService *secretsManager.SecretsService, | ||||
| 	// Need to make sure these are initialized, is there a better place to put them?
 | ||||
| 	_ *azuremonitor.Service, _ *cloudwatch.CloudWatchService, _ *elasticsearch.Service, _ *graphite.Service, | ||||
| 	_ *influxdb.Service, _ *loki.Service, _ *opentsdb.Service, _ *prometheus.Service, _ *tempo.Service, | ||||
| 	_ *testdatasource.Service, _ *plugindashboards.Service, _ *dashboardsnapshots.Service, | ||||
| 	_ *postgres.Service, _ *mysql.Service, _ *mssql.Service, _ *grafanads.Service, _ *cloudmonitoring.Service, | ||||
| 	_ *pluginsettings.Service, _ *alerting.AlertNotificationService, _ serviceaccounts.Service, | ||||
| 	_ *plugindashboards.Service, _ *dashboardsnapshots.Service, _ *pluginsettings.Service, | ||||
| 	_ *alerting.AlertNotificationService, _ serviceaccounts.Service, | ||||
| ) *BackgroundServiceRegistry { | ||||
| 	return NewBackgroundServiceRegistry( | ||||
| 		httpServer, | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ import ( | |||
| 	"github.com/grafana/grafana/pkg/login/social" | ||||
| 	"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/plugins/manager" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/manager/loader" | ||||
| 	"github.com/grafana/grafana/pkg/plugins/plugincontext" | ||||
|  | @ -112,6 +113,7 @@ var wireBasicSet = wire.NewSet( | |||
| 	wire.Bind(new(plugins.StaticRouteResolver), new(*manager.PluginManager)), | ||||
| 	wire.Bind(new(plugins.PluginDashboardManager), new(*manager.PluginManager)), | ||||
| 	wire.Bind(new(plugins.RendererManager), new(*manager.PluginManager)), | ||||
| 	coreplugin.ProvideCoreRegistry, | ||||
| 	loader.ProvideService, | ||||
| 	wire.Bind(new(plugins.Loader), new(*loader.Loader)), | ||||
| 	wire.Bind(new(plugins.ErrorResolver), new(*loader.Loader)), | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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{ | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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 | ||||
| 	} | ||||
|  |  | |||
|  | @ -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 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 | ||||
| } | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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) { | ||||
|  |  | |||
|  | @ -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"), | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 ( | ||||
|  |  | |||
|  | @ -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) { | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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) { | ||||
|  |  | |||
|  | @ -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) | ||||
| } | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
|   "name": "-- Grafana --", | ||||
|   "id": "grafana", | ||||
| 
 | ||||
|   "backend": true, | ||||
|   "builtIn": true, | ||||
|   "annotations": true, | ||||
|   "metrics": true | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue