diff --git a/pkg/plugins/backendplugin/coreplugin/registry.go b/pkg/plugins/backendplugin/coreplugin/registry.go index 44c8a045e33..6bdc87331d3 100644 --- a/pkg/plugins/backendplugin/coreplugin/registry.go +++ b/pkg/plugins/backendplugin/coreplugin/registry.go @@ -2,15 +2,20 @@ package coreplugin import ( "context" + "errors" + "fmt" "github.com/grafana/grafana-plugin-sdk-go/backend" sdklog "github.com/grafana/grafana-plugin-sdk-go/backend/log" sdktracing "github.com/grafana/grafana-plugin-sdk-go/backend/tracing" + "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/backendplugin" "github.com/grafana/grafana/pkg/plugins/log" + "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/tsdb/azuremonitor" cloudmonitoring "github.com/grafana/grafana/pkg/tsdb/cloud-monitoring" "github.com/grafana/grafana/pkg/tsdb/cloudwatch" @@ -42,6 +47,7 @@ const ( Prometheus = "prometheus" Tempo = "tempo" TestData = "grafana-testdata-datasource" + TestDataAlias = "testdata" PostgreSQL = "grafana-postgresql-datasource" MySQL = "mysql" MSSQL = "mssql" @@ -182,3 +188,73 @@ func (l *logWrapper) FromContext(ctx context.Context) sdklog.Logger { logger: l.logger.FromContext(ctx), } } + +var ErrCorePluginNotFound = errors.New("core plugin not found") + +// NewPlugin factory for creating and initializing a single core plugin. +// Note: cfg only needed for mssql connection pooling defaults. +func NewPlugin(pluginID string, cfg *setting.Cfg, httpClientProvider *httpclient.Provider, tracer tracing.Tracer, features featuremgmt.FeatureToggles) (*plugins.Plugin, error) { + jsonData := plugins.JSONData{ + ID: pluginID, + AliasIDs: []string{}, + } + var svc any + + switch pluginID { + case TestData, TestDataAlias: + jsonData.ID = TestData + jsonData.AliasIDs = append(jsonData.AliasIDs, TestDataAlias) + svc = testdatasource.ProvideService() + case CloudWatch: + svc = cloudwatch.ProvideService(httpClientProvider).Executor + case CloudMonitoring: + svc = cloudmonitoring.ProvideService(httpClientProvider) + case AzureMonitor: + svc = azuremonitor.ProvideService(httpClientProvider) + case Elasticsearch: + svc = elasticsearch.ProvideService(httpClientProvider, tracer) + case Graphite: + svc = graphite.ProvideService(httpClientProvider, tracer) + case InfluxDB: + svc = influxdb.ProvideService(httpClientProvider, features) + case Loki: + svc = loki.ProvideService(httpClientProvider, features, tracer) + case OpenTSDB: + svc = opentsdb.ProvideService(httpClientProvider) + case Prometheus: + svc = prometheus.ProvideService(httpClientProvider) + case Tempo: + svc = tempo.ProvideService(httpClientProvider) + case PostgreSQL: + svc = postgres.ProvideService(cfg) + case MySQL: + svc = mysql.ProvideService() + case MSSQL: + svc = mssql.ProvideService(cfg) + case Pyroscope: + svc = pyroscope.ProvideService(httpClientProvider) + case Parca: + svc = parca.ProvideService(httpClientProvider) + default: + return nil, ErrCorePluginNotFound + } + + p := plugins.Plugin{ + JSONData: jsonData, + Class: plugins.ClassCore, + } + + p.SetLogger(log.New(fmt.Sprintf("plugin.%s", p.ID))) + + backendFactory := asBackendPlugin(svc) + if backendFactory == nil { + return nil, ErrCorePluginNotFound + } + bp, err := backendFactory(p.ID, p.Logger(), nil) + if err != nil { + return nil, err + } + p.RegisterClient(bp) + + return &p, nil +} diff --git a/pkg/plugins/backendplugin/coreplugin/registry_test.go b/pkg/plugins/backendplugin/coreplugin/registry_test.go new file mode 100644 index 00000000000..31460f92964 --- /dev/null +++ b/pkg/plugins/backendplugin/coreplugin/registry_test.go @@ -0,0 +1,63 @@ +package coreplugin + +import ( + "testing" + + "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" + "github.com/grafana/grafana/pkg/infra/tracing" + "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/setting" + "github.com/stretchr/testify/require" +) + +func TestNewPlugin(t *testing.T) { + tcs := []struct { + ID string + ExpectedID string + ExpectedAlias string + ExpectedNotFoundErr bool + }{ + {ID: AzureMonitor}, + {ID: CloudMonitoring}, + {ID: CloudWatch}, + {ID: Elasticsearch}, + {ID: Grafana, ExpectedNotFoundErr: true}, + {ID: Graphite}, + {ID: InfluxDB}, + {ID: Loki}, + {ID: MSSQL}, + {ID: MySQL}, + {ID: OpenTSDB}, + {ID: Parca}, + {ID: PostgreSQL}, + {ID: Prometheus}, + {ID: Pyroscope}, + {ID: Tempo}, + {ID: TestData, ExpectedAlias: TestDataAlias}, + {ID: TestDataAlias, ExpectedID: TestData, ExpectedAlias: TestDataAlias}, + } + + for _, tc := range tcs { + t.Run(tc.ID, func(t *testing.T) { + if tc.ExpectedID == "" { + tc.ExpectedID = tc.ID + } + + p, err := NewPlugin(tc.ID, setting.NewCfg(), httpclient.NewProvider(), tracing.InitializeTracerForTest(), featuremgmt.WithFeatures()) + if tc.ExpectedNotFoundErr { + require.ErrorIs(t, err, ErrCorePluginNotFound) + require.Nil(t, p) + } else { + require.NoError(t, err) + require.NotNil(t, p) + require.Equal(t, tc.ExpectedID, p.ID) + if tc.ExpectedAlias != "" { + require.Equal(t, tc.ExpectedAlias, p.AliasIDs[0]) + } + c, exists := p.Client() + require.True(t, exists) + require.NotNil(t, c) + } + }) + } +}