Plugins: Move store and plugin dto to pluginsintegration (#74655)
move store and plugin dto
This commit is contained in:
@@ -7,11 +7,11 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/dashboardimport"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
@@ -19,12 +19,12 @@ import (
|
||||
type ImportDashboardAPI struct {
|
||||
dashboardImportService dashboardimport.Service
|
||||
quotaService QuotaService
|
||||
pluginStore plugins.Store
|
||||
pluginStore pluginstore.Store
|
||||
ac accesscontrol.AccessControl
|
||||
}
|
||||
|
||||
func New(dashboardImportService dashboardimport.Service, quotaService QuotaService,
|
||||
pluginStore plugins.Store, ac accesscontrol.AccessControl) *ImportDashboardAPI {
|
||||
pluginStore pluginstore.Store, ac accesscontrol.AccessControl) *ImportDashboardAPI {
|
||||
return &ImportDashboardAPI{
|
||||
dashboardImportService: dashboardImportService,
|
||||
quotaService: quotaService,
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/dashboardimport"
|
||||
@@ -15,12 +14,13 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/librarypanels"
|
||||
"github.com/grafana/grafana/pkg/services/plugindashboards"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
)
|
||||
|
||||
func ProvideService(routeRegister routing.RouteRegister,
|
||||
quotaService quota.Service,
|
||||
pluginDashboardService plugindashboards.Service, pluginStore plugins.Store,
|
||||
pluginDashboardService plugindashboards.Service, pluginStore pluginstore.Store,
|
||||
libraryPanelService librarypanels.Service, dashboardService dashboards.DashboardService,
|
||||
ac accesscontrol.AccessControl, folderService folder.Service,
|
||||
) *ImportDashboardService {
|
||||
|
||||
@@ -12,10 +12,10 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/oauthtoken"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
"github.com/grafana/grafana/pkg/services/validations"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
)
|
||||
|
||||
func ProvideService(dataSourceCache datasources.CacheService, plugReqValidator validations.PluginRequestValidator,
|
||||
pluginStore plugins.Store, cfg *setting.Cfg, httpClientProvider httpclient.Provider,
|
||||
pluginStore pluginstore.Store, cfg *setting.Cfg, httpClientProvider httpclient.Provider,
|
||||
oauthTokenService *oauthtoken.Service, dsService datasources.DataSourceService,
|
||||
tracer tracing.Tracer, secretsService secrets.Service) *DataSourceProxyService {
|
||||
return &DataSourceProxyService{
|
||||
@@ -43,7 +43,7 @@ func ProvideService(dataSourceCache datasources.CacheService, plugReqValidator v
|
||||
type DataSourceProxyService struct {
|
||||
DataSourceCache datasources.CacheService
|
||||
PluginRequestValidator validations.PluginRequestValidator
|
||||
pluginStore plugins.Store
|
||||
pluginStore pluginstore.Store
|
||||
Cfg *setting.Cfg
|
||||
HTTPClientProvider httpclient.Provider
|
||||
OAuthTokenService *oauthtoken.Service
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -88,7 +88,7 @@ func TestDatasourceProxy_proxyDatasourceRequest(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
pluginID := datasources.DS_PROMETHEUS
|
||||
|
||||
pluginStore := &fakes.FakePluginStore{PluginList: []plugins.PluginDTO{
|
||||
pluginStore := &pluginstore.FakePluginStore{PluginList: []pluginstore.Plugin{
|
||||
{JSONData: plugins.JSONData{ID: pluginID}},
|
||||
}}
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/live/survey"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/query"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
@@ -73,7 +74,7 @@ type CoreGrafanaScope struct {
|
||||
}
|
||||
|
||||
func ProvideService(plugCtxProvider *plugincontext.Provider, cfg *setting.Cfg, routeRegister routing.RouteRegister,
|
||||
pluginStore plugins.Store, pluginClient plugins.Client, cacheService *localcache.CacheService,
|
||||
pluginStore pluginstore.Store, pluginClient plugins.Client, cacheService *localcache.CacheService,
|
||||
dataSourceCache datasources.CacheService, sqlStore db.DB, secretsService secrets.Service,
|
||||
usageStatsService usagestats.Service, queryDataService query.Service, toggles featuremgmt.FeatureToggles,
|
||||
accessControl accesscontrol.AccessControl, dashboardService dashboards.DashboardService, annotationsRepo annotations.Repository,
|
||||
@@ -356,7 +357,7 @@ type GrafanaLive struct {
|
||||
DataSourceCache datasources.CacheService
|
||||
SQLStore db.DB
|
||||
SecretsService secrets.Service
|
||||
pluginStore plugins.Store
|
||||
pluginStore pluginstore.Store
|
||||
pluginClient plugins.Client
|
||||
queryDataService query.Service
|
||||
orgService org.Service
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/navtree"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
@@ -24,7 +25,7 @@ func (s *ServiceImpl) addAppLinks(treeRoot *navtree.NavTreeRoot, c *contextmodel
|
||||
return err
|
||||
}
|
||||
|
||||
isPluginEnabled := func(plugin plugins.PluginDTO) bool {
|
||||
isPluginEnabled := func(plugin pluginstore.Plugin) bool {
|
||||
if plugin.AutoEnabled {
|
||||
return true
|
||||
}
|
||||
@@ -63,7 +64,7 @@ func (s *ServiceImpl) addAppLinks(treeRoot *navtree.NavTreeRoot, c *contextmodel
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ServiceImpl) processAppPlugin(plugin plugins.PluginDTO, c *contextmodel.ReqContext, treeRoot *navtree.NavTreeRoot) *navtree.NavLink {
|
||||
func (s *ServiceImpl) processAppPlugin(plugin pluginstore.Plugin, c *contextmodel.ReqContext, treeRoot *navtree.NavTreeRoot) *navtree.NavLink {
|
||||
hasAccessToInclude := s.hasAccessToInclude(c, plugin.ID)
|
||||
appLink := &navtree.NavLink{
|
||||
Text: plugin.Name,
|
||||
@@ -165,7 +166,7 @@ func (s *ServiceImpl) processAppPlugin(plugin plugins.PluginDTO, c *contextmodel
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ServiceImpl) addPluginToSection(c *contextmodel.ReqContext, treeRoot *navtree.NavTreeRoot, plugin plugins.PluginDTO, appLink *navtree.NavLink) {
|
||||
func (s *ServiceImpl) addPluginToSection(c *contextmodel.ReqContext, treeRoot *navtree.NavTreeRoot, plugin pluginstore.Plugin, appLink *navtree.NavLink) {
|
||||
// Handle moving apps into specific navtree sections
|
||||
alertingNode := treeRoot.FindById(navtree.NavIDAlerting)
|
||||
if alertingNode == nil {
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models/roletype"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
@@ -19,6 +18,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/navtree"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
@@ -34,7 +34,7 @@ func TestAddAppLinks(t *testing.T) {
|
||||
{Action: datasources.ActionRead, Scope: "*"},
|
||||
}
|
||||
|
||||
testApp1 := plugins.PluginDTO{
|
||||
testApp1 := pluginstore.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test-app1",
|
||||
Name: "Test app1 name",
|
||||
@@ -57,7 +57,7 @@ func TestAddAppLinks(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
testApp2 := plugins.PluginDTO{
|
||||
testApp2 := pluginstore.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test-app2",
|
||||
Name: "Test app2 name",
|
||||
@@ -74,7 +74,7 @@ func TestAddAppLinks(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
testApp3 := plugins.PluginDTO{
|
||||
testApp3 := pluginstore.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test-app3",
|
||||
Name: "Test app3 name",
|
||||
@@ -115,8 +115,8 @@ func TestAddAppLinks(t *testing.T) {
|
||||
accessControl: accesscontrolmock.New().WithPermissions(permissions),
|
||||
pluginSettings: &pluginSettings,
|
||||
features: featuremgmt.WithFeatures(),
|
||||
pluginStore: &fakes.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{testApp1, testApp2, testApp3},
|
||||
pluginStore: &pluginstore.FakePluginStore{
|
||||
PluginList: []pluginstore.Plugin{testApp1, testApp2, testApp3},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -399,7 +399,7 @@ func TestAddAppLinksAccessControl(t *testing.T) {
|
||||
reqCtx := &contextmodel.ReqContext{SignedInUser: user, Context: &web.Context{Req: httpReq}}
|
||||
catalogReadAction := "test-app1.catalog:read"
|
||||
|
||||
testApp1 := plugins.PluginDTO{
|
||||
testApp1 := pluginstore.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test-app1", Name: "Test app1 name", Type: plugins.TypeApp,
|
||||
Includes: []*plugins.Includes{
|
||||
@@ -435,8 +435,8 @@ func TestAddAppLinksAccessControl(t *testing.T) {
|
||||
accessControl: acimpl.ProvideAccessControl(cfg),
|
||||
pluginSettings: &pluginSettings,
|
||||
features: featuremgmt.WithFeatures(),
|
||||
pluginStore: &fakes.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{testApp1},
|
||||
pluginStore: &pluginstore.FakePluginStore{
|
||||
PluginList: []pluginstore.Plugin{testApp1},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/apikey"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
@@ -18,6 +17,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/navtree"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
pref "github.com/grafana/grafana/pkg/services/preference"
|
||||
"github.com/grafana/grafana/pkg/services/star"
|
||||
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlesimpl"
|
||||
@@ -28,7 +28,7 @@ type ServiceImpl struct {
|
||||
cfg *setting.Cfg
|
||||
log log.Logger
|
||||
accessControl ac.AccessControl
|
||||
pluginStore plugins.Store
|
||||
pluginStore pluginstore.Store
|
||||
pluginSettings pluginsettings.Service
|
||||
starService star.Service
|
||||
features *featuremgmt.FeatureManager
|
||||
@@ -50,7 +50,7 @@ type NavigationAppConfig struct {
|
||||
Icon string
|
||||
}
|
||||
|
||||
func ProvideService(cfg *setting.Cfg, accessControl ac.AccessControl, pluginStore plugins.Store, pluginSettings pluginsettings.Service, starService star.Service, features *featuremgmt.FeatureManager, dashboardService dashboards.DashboardService, accesscontrolService ac.Service, kvStore kvstore.KVStore, apiKeyService apikey.Service, license licensing.Licensing) navtree.Service {
|
||||
func ProvideService(cfg *setting.Cfg, accessControl ac.AccessControl, pluginStore pluginstore.Store, pluginSettings pluginsettings.Service, starService star.Service, features *featuremgmt.FeatureManager, dashboardService dashboards.DashboardService, accesscontrolService ac.Service, kvStore kvstore.KVStore, apiKeyService apikey.Service, license licensing.Licensing) navtree.Service {
|
||||
service := &ServiceImpl{
|
||||
cfg: cfg,
|
||||
log: log.New("navtree service"),
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -88,14 +89,14 @@ type evaluatorImpl struct {
|
||||
evaluationTimeout time.Duration
|
||||
dataSourceCache datasources.CacheService
|
||||
expressionService *expr.Service
|
||||
pluginsStore plugins.Store
|
||||
pluginsStore pluginstore.Store
|
||||
}
|
||||
|
||||
func NewEvaluatorFactory(
|
||||
cfg setting.UnifiedAlertingSettings,
|
||||
datasourceCache datasources.CacheService,
|
||||
expressionService *expr.Service,
|
||||
pluginsStore plugins.Store,
|
||||
pluginsStore pluginstore.Store,
|
||||
) EvaluatorFactory {
|
||||
return &evaluatorImpl{
|
||||
evaluationTimeout: cfg.EvaluationTimeout,
|
||||
|
||||
@@ -15,11 +15,11 @@ import (
|
||||
"github.com/grafana/grafana/pkg/expr"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
pluginFakes "github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
fakes "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@@ -359,7 +359,7 @@ func TestEvaluateExecutionResultsNoData(t *testing.T) {
|
||||
func TestValidate(t *testing.T) {
|
||||
type services struct {
|
||||
cache *fakes.FakeCacheService
|
||||
pluginsStore *pluginFakes.FakePluginStore
|
||||
pluginsStore *pluginstore.FakePluginStore
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
@@ -387,7 +387,7 @@ func TestValidate(t *testing.T) {
|
||||
Type: util.GenerateShortUID(),
|
||||
}
|
||||
services.cache.DataSources = append(services.cache.DataSources, ds)
|
||||
services.pluginsStore.PluginList = append(services.pluginsStore.PluginList, plugins.PluginDTO{
|
||||
services.pluginsStore.PluginList = append(services.pluginsStore.PluginList, pluginstore.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: ds.Type,
|
||||
Backend: true,
|
||||
@@ -413,7 +413,7 @@ func TestValidate(t *testing.T) {
|
||||
Type: util.GenerateShortUID(),
|
||||
}
|
||||
services.cache.DataSources = append(services.cache.DataSources, ds)
|
||||
services.pluginsStore.PluginList = append(services.pluginsStore.PluginList, plugins.PluginDTO{
|
||||
services.pluginsStore.PluginList = append(services.pluginsStore.PluginList, pluginstore.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: ds.Type,
|
||||
Backend: true,
|
||||
@@ -476,12 +476,12 @@ func TestValidate(t *testing.T) {
|
||||
Type: util.GenerateShortUID(),
|
||||
}
|
||||
services.cache.DataSources = append(services.cache.DataSources, ds1, ds2)
|
||||
services.pluginsStore.PluginList = append(services.pluginsStore.PluginList, plugins.PluginDTO{
|
||||
services.pluginsStore.PluginList = append(services.pluginsStore.PluginList, pluginstore.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: ds1.Type,
|
||||
Backend: false,
|
||||
},
|
||||
}, plugins.PluginDTO{
|
||||
}, pluginstore.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: ds2.Type,
|
||||
Backend: true,
|
||||
@@ -507,7 +507,7 @@ func TestValidate(t *testing.T) {
|
||||
Type: util.GenerateShortUID(),
|
||||
}
|
||||
services.cache.DataSources = append(services.cache.DataSources, ds)
|
||||
services.pluginsStore.PluginList = append(services.pluginsStore.PluginList, plugins.PluginDTO{
|
||||
services.pluginsStore.PluginList = append(services.pluginsStore.PluginList, pluginstore.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: ds.Type,
|
||||
Backend: true,
|
||||
@@ -530,7 +530,7 @@ func TestValidate(t *testing.T) {
|
||||
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
cacheService := &fakes.FakeCacheService{}
|
||||
store := &pluginFakes.FakePluginStore{}
|
||||
store := &pluginstore.FakePluginStore{}
|
||||
condition := testCase.condition(services{
|
||||
cache: cacheService,
|
||||
pluginsStore: store,
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"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/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/annotations"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
@@ -38,6 +37,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/state/historian"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"github.com/grafana/grafana/pkg/services/rendering"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
@@ -65,7 +65,7 @@ func ProvideService(
|
||||
bus bus.Bus,
|
||||
accesscontrolService accesscontrol.Service,
|
||||
annotationsRepo annotations.Repository,
|
||||
pluginsStore plugins.Store,
|
||||
pluginsStore pluginstore.Store,
|
||||
tracer tracing.Tracer,
|
||||
ruleStore *store.DBstore,
|
||||
) (*AlertNG, error) {
|
||||
@@ -140,7 +140,7 @@ type AlertNG struct {
|
||||
store *store.DBstore
|
||||
|
||||
bus bus.Bus
|
||||
pluginsStore plugins.Store
|
||||
pluginsStore pluginstore.Store
|
||||
tracer tracing.Tracer
|
||||
}
|
||||
|
||||
|
||||
@@ -23,13 +23,13 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/expr"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/eval"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/metrics"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/state"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
@@ -855,7 +855,7 @@ func setupScheduler(t *testing.T, rs *fakeRulesStore, is *state.FakeInstanceStor
|
||||
|
||||
var evaluator = evalMock
|
||||
if evalMock == nil {
|
||||
evaluator = eval.NewEvaluatorFactory(setting.UnifiedAlertingSettings{}, nil, expr.ProvideService(&setting.Cfg{ExpressionsEnabled: true}, nil, nil, &featuremgmt.FeatureManager{}, nil, tracing.InitializeTracerForTest()), &fakes.FakePluginStore{})
|
||||
evaluator = eval.NewEvaluatorFactory(setting.UnifiedAlertingSettings{}, nil, expr.ProvideService(&setting.Cfg{ExpressionsEnabled: true}, nil, nil, &featuremgmt.FeatureManager{}, nil, tracing.InitializeTracerForTest()), &pluginstore.FakePluginStore{})
|
||||
}
|
||||
|
||||
if registry == nil {
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/annotations/annotationstest"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
@@ -30,6 +29,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/testutil"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/database"
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
@@ -68,7 +68,7 @@ func SetupTestEnv(tb testing.TB, baseInterval time.Duration) (*ngalert.AlertNG,
|
||||
ng, err := ngalert.ProvideService(
|
||||
cfg, featuremgmt.WithFeatures(), nil, nil, routing.NewRouteRegister(), sqlStore, nil, nil, nil, quotatest.New(false, nil),
|
||||
secretsService, nil, m, folderService, ac, &dashboards.FakeDashboardService{}, nil, bus, ac,
|
||||
annotationstest.NewFakeAnnotationsRepo(), &fakes.FakePluginStore{}, tracer, ruleStore,
|
||||
annotationstest.NewFakeAnnotationsRepo(), &pluginstore.FakePluginStore{}, tracer, ruleStore,
|
||||
)
|
||||
require.NoError(tb, err)
|
||||
return ng, &store.DBstore{
|
||||
|
||||
@@ -6,16 +6,16 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/dashboardimport"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/plugindashboards"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
)
|
||||
|
||||
func ProvideDashboardUpdater(bus bus.Bus, pluginStore plugins.Store, pluginDashboardService plugindashboards.Service,
|
||||
func ProvideDashboardUpdater(bus bus.Bus, pluginStore pluginstore.Store, pluginDashboardService plugindashboards.Service,
|
||||
dashboardImportService dashboardimport.Service, pluginSettingsService pluginsettings.Service,
|
||||
dashboardPluginService dashboards.PluginService, dashboardService dashboards.DashboardService) *DashboardUpdater {
|
||||
du := newDashboardUpdater(bus, pluginStore, pluginDashboardService, dashboardImportService,
|
||||
@@ -24,7 +24,7 @@ func ProvideDashboardUpdater(bus bus.Bus, pluginStore plugins.Store, pluginDashb
|
||||
return du
|
||||
}
|
||||
|
||||
func newDashboardUpdater(bus bus.Bus, pluginStore plugins.Store,
|
||||
func newDashboardUpdater(bus bus.Bus, pluginStore pluginstore.Store,
|
||||
pluginDashboardService plugindashboards.Service, dashboardImportService dashboardimport.Service,
|
||||
pluginSettingsService pluginsettings.Service, dashboardPluginService dashboards.PluginService,
|
||||
dashboardService dashboards.DashboardService) *DashboardUpdater {
|
||||
@@ -43,7 +43,7 @@ func newDashboardUpdater(bus bus.Bus, pluginStore plugins.Store,
|
||||
}
|
||||
|
||||
type DashboardUpdater struct {
|
||||
pluginStore plugins.Store
|
||||
pluginStore pluginstore.Store
|
||||
pluginDashboardService plugindashboards.Service
|
||||
dashboardImportService dashboardimport.Service
|
||||
pluginSettingsService pluginsettings.Service
|
||||
@@ -75,7 +75,7 @@ func (du *DashboardUpdater) updateAppDashboards() {
|
||||
}
|
||||
}
|
||||
|
||||
func (du *DashboardUpdater) syncPluginDashboards(ctx context.Context, plugin plugins.PluginDTO, orgID int64) {
|
||||
func (du *DashboardUpdater) syncPluginDashboards(ctx context.Context, plugin pluginstore.Plugin, orgID int64) {
|
||||
du.logger.Info("Syncing plugin dashboards to DB", "pluginId", plugin.ID)
|
||||
|
||||
// Get plugin dashboards
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/plugindashboards"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings/service"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
)
|
||||
|
||||
func TestDashboardUpdater(t *testing.T) {
|
||||
@@ -83,7 +84,7 @@ func TestDashboardUpdater(t *testing.T) {
|
||||
PluginVersion: "1.0.0",
|
||||
},
|
||||
},
|
||||
installedPlugins: []plugins.PluginDTO{
|
||||
installedPlugins: []pluginstore.Plugin{
|
||||
{
|
||||
JSONData: plugins.JSONData{
|
||||
Info: plugins.Info{
|
||||
@@ -115,7 +116,7 @@ func TestDashboardUpdater(t *testing.T) {
|
||||
PluginVersion: "1.0.0",
|
||||
},
|
||||
},
|
||||
installedPlugins: []plugins.PluginDTO{
|
||||
installedPlugins: []pluginstore.Plugin{
|
||||
{
|
||||
JSONData: plugins.JSONData{
|
||||
Info: plugins.Info{
|
||||
@@ -151,7 +152,7 @@ func TestDashboardUpdater(t *testing.T) {
|
||||
OrgID: 2,
|
||||
},
|
||||
},
|
||||
installedPlugins: []plugins.PluginDTO{
|
||||
installedPlugins: []pluginstore.Plugin{
|
||||
{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test",
|
||||
@@ -225,7 +226,7 @@ func TestDashboardUpdater(t *testing.T) {
|
||||
OrgID: 2,
|
||||
},
|
||||
},
|
||||
installedPlugins: []plugins.PluginDTO{
|
||||
installedPlugins: []pluginstore.Plugin{
|
||||
{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test",
|
||||
@@ -273,7 +274,7 @@ func TestDashboardUpdater(t *testing.T) {
|
||||
PluginVersion: "1.0.0",
|
||||
},
|
||||
},
|
||||
installedPlugins: []plugins.PluginDTO{
|
||||
installedPlugins: []pluginstore.Plugin{
|
||||
{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test",
|
||||
@@ -341,16 +342,16 @@ func TestDashboardUpdater(t *testing.T) {
|
||||
}
|
||||
|
||||
type pluginStoreMock struct {
|
||||
plugins.Store
|
||||
pluginFunc func(ctx context.Context, pluginID string) (plugins.PluginDTO, bool)
|
||||
pluginstore.Store
|
||||
pluginFunc func(ctx context.Context, pluginID string) (pluginstore.Plugin, bool)
|
||||
}
|
||||
|
||||
func (m *pluginStoreMock) Plugin(ctx context.Context, pluginID string) (plugins.PluginDTO, bool) {
|
||||
func (m *pluginStoreMock) Plugin(ctx context.Context, pluginID string) (pluginstore.Plugin, bool) {
|
||||
if m.pluginFunc != nil {
|
||||
return m.pluginFunc(ctx, pluginID)
|
||||
}
|
||||
|
||||
return plugins.PluginDTO{}, false
|
||||
return pluginstore.Plugin{}, false
|
||||
}
|
||||
|
||||
type pluginDashboardServiceMock struct {
|
||||
@@ -464,7 +465,7 @@ func (s *dashboardServiceMock) GetDashboardByPublicUid(ctx context.Context, dash
|
||||
|
||||
type scenarioInput struct {
|
||||
storedPluginSettings []*pluginsettings.DTO
|
||||
installedPlugins []plugins.PluginDTO
|
||||
installedPlugins []pluginstore.Plugin
|
||||
pluginDashboards []*plugindashboards.PluginDashboard
|
||||
}
|
||||
|
||||
@@ -472,7 +473,7 @@ type scenarioContext struct {
|
||||
t *testing.T
|
||||
bus bus.Bus
|
||||
pluginSettingsService *pluginsSettingsServiceMock
|
||||
pluginStore plugins.Store
|
||||
pluginStore pluginstore.Store
|
||||
pluginDashboardService plugindashboards.Service
|
||||
importDashboardService dashboardimport.Service
|
||||
dashboardPluginService *dashboardPluginServiceMock
|
||||
@@ -496,14 +497,14 @@ func scenario(t *testing.T, desc string, input scenarioInput, f func(ctx *scenar
|
||||
updatePluginSettingVersionArgs: []*pluginsettings.UpdatePluginSettingVersionCmd{},
|
||||
}
|
||||
|
||||
getPlugin := func(ctx context.Context, pluginID string) (plugins.PluginDTO, bool) {
|
||||
getPlugin := func(ctx context.Context, pluginID string) (pluginstore.Plugin, bool) {
|
||||
for _, p := range input.installedPlugins {
|
||||
if p.ID == pluginID {
|
||||
return p, true
|
||||
}
|
||||
}
|
||||
|
||||
return plugins.PluginDTO{}, false
|
||||
return pluginstore.Plugin{}, false
|
||||
}
|
||||
|
||||
sCtx.pluginSettingsService = &pluginsSettingsServiceMock{
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
pluginDashboardsManager "github.com/grafana/grafana/pkg/plugins/manager/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/plugindashboards"
|
||||
pluginDashboardsManager "github.com/grafana/grafana/pkg/services/pluginsintegration/dashboards"
|
||||
)
|
||||
|
||||
func ProvideService(pluginDashboardStore pluginDashboardsManager.FileStore, dashboardPluginService dashboards.PluginService) *Service {
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/dashboards"
|
||||
dashmodels "github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/plugindashboards"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/dashboards"
|
||||
)
|
||||
|
||||
func TestGetPluginDashboards(t *testing.T) {
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package dashboards
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
var _ FileStore = (*FileStoreManager)(nil)
|
||||
|
||||
type FileStoreManager struct {
|
||||
pluginStore pluginstore.Store
|
||||
pluginFileStore plugins.FileStore
|
||||
}
|
||||
|
||||
func ProvideFileStoreManager(pluginStore pluginstore.Store, pluginFileStore plugins.FileStore) *FileStoreManager {
|
||||
return &FileStoreManager{
|
||||
pluginStore: pluginStore,
|
||||
pluginFileStore: pluginFileStore,
|
||||
}
|
||||
}
|
||||
|
||||
var openDashboardFile = func(ctx context.Context, pluginFileStore plugins.FileStore, pluginID, name string) (*plugins.File, error) {
|
||||
f, err := pluginFileStore.File(ctx, pluginID, name)
|
||||
if err != nil {
|
||||
return &plugins.File{}, err
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (m *FileStoreManager) ListPluginDashboardFiles(ctx context.Context, args *ListPluginDashboardFilesArgs) (*ListPluginDashboardFilesResult, error) {
|
||||
if args == nil {
|
||||
return nil, errors.New("args cannot be nil")
|
||||
}
|
||||
|
||||
if len(strings.TrimSpace(args.PluginID)) == 0 {
|
||||
return nil, errors.New("args.PluginID cannot be empty")
|
||||
}
|
||||
|
||||
plugin, exists := m.pluginStore.Plugin(ctx, args.PluginID)
|
||||
if !exists {
|
||||
return nil, plugins.NotFoundError{PluginID: args.PluginID}
|
||||
}
|
||||
|
||||
references := []string{}
|
||||
for _, include := range plugin.DashboardIncludes() {
|
||||
references = append(references, include.Path)
|
||||
}
|
||||
|
||||
return &ListPluginDashboardFilesResult{
|
||||
FileReferences: references,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *FileStoreManager) GetPluginDashboardFileContents(ctx context.Context, args *GetPluginDashboardFileContentsArgs) (*GetPluginDashboardFileContentsResult, error) {
|
||||
if args == nil {
|
||||
return nil, errors.New("args cannot be nil")
|
||||
}
|
||||
|
||||
if len(strings.TrimSpace(args.PluginID)) == 0 {
|
||||
return nil, errors.New("args.PluginID cannot be empty")
|
||||
}
|
||||
|
||||
if len(strings.TrimSpace(args.FileReference)) == 0 {
|
||||
return nil, errors.New("args.FileReference cannot be empty")
|
||||
}
|
||||
|
||||
plugin, exists := m.pluginStore.Plugin(ctx, args.PluginID)
|
||||
if !exists {
|
||||
return nil, plugins.NotFoundError{PluginID: args.PluginID}
|
||||
}
|
||||
|
||||
var includedFile *plugins.Includes
|
||||
for _, include := range plugin.DashboardIncludes() {
|
||||
if args.FileReference == include.Path {
|
||||
includedFile = include
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if includedFile == nil {
|
||||
return nil, errors.New("plugin dashboard file not found")
|
||||
}
|
||||
|
||||
cleanPath, err := util.CleanRelativePath(includedFile.Path)
|
||||
if err != nil {
|
||||
// CleanRelativePath should clean and make the path relative so this is not expected to fail
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file, err := openDashboardFile(ctx, m.pluginFileStore, plugin.ID, cleanPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &GetPluginDashboardFileContentsResult{
|
||||
Content: file.Content,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package dashboards
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
)
|
||||
|
||||
func TestDashboardFileStore(t *testing.T) {
|
||||
m := setupPluginDashboardsForTest(t)
|
||||
|
||||
t.Run("Input validation", func(t *testing.T) {
|
||||
t.Run("ListPluginDashboardFiles", func(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args *ListPluginDashboardFilesArgs
|
||||
}{
|
||||
{
|
||||
name: "nil args should return error",
|
||||
},
|
||||
{
|
||||
name: "empty args.PluginID should return error",
|
||||
args: &ListPluginDashboardFilesArgs{},
|
||||
},
|
||||
{
|
||||
name: "args.PluginID with only space should return error",
|
||||
args: &ListPluginDashboardFilesArgs{PluginID: " \t "},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
res, err := m.ListPluginDashboardFiles(context.Background(), tc.args)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, res)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("GetPluginDashboardFileContents", func(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args *GetPluginDashboardFileContentsArgs
|
||||
}{
|
||||
{
|
||||
name: "nil args should return error",
|
||||
},
|
||||
{
|
||||
name: "empty args.PluginID should return error",
|
||||
args: &GetPluginDashboardFileContentsArgs{},
|
||||
},
|
||||
{
|
||||
name: "args.PluginID with only space should return error",
|
||||
args: &GetPluginDashboardFileContentsArgs{PluginID: " "},
|
||||
},
|
||||
{
|
||||
name: "empty args.FileReference should return error",
|
||||
args: &GetPluginDashboardFileContentsArgs{
|
||||
PluginID: "pluginWithDashboards",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "args.FileReference with only space should return error",
|
||||
args: &GetPluginDashboardFileContentsArgs{
|
||||
PluginID: "pluginWithDashboard",
|
||||
FileReference: " \t",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
res, err := m.GetPluginDashboardFileContents(context.Background(), tc.args)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, res)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Plugin without dashboards", func(t *testing.T) {
|
||||
t.Run("Should return zero file references", func(t *testing.T) {
|
||||
res, err := m.ListPluginDashboardFiles(context.Background(), &ListPluginDashboardFilesArgs{
|
||||
PluginID: "pluginWithoutDashboards",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
require.Len(t, res.FileReferences, 0)
|
||||
})
|
||||
|
||||
t.Run("Should return file not found error when trying to get non-existing plugin dashboard file content", func(t *testing.T) {
|
||||
res, err := m.GetPluginDashboardFileContents(context.Background(), &GetPluginDashboardFileContentsArgs{
|
||||
PluginID: "pluginWithoutDashboards",
|
||||
FileReference: "dashboards/dash2.json",
|
||||
})
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, "plugin dashboard file not found")
|
||||
require.Nil(t, res)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Plugin with dashboards", func(t *testing.T) {
|
||||
t.Run("Should return two file references", func(t *testing.T) {
|
||||
res, err := m.ListPluginDashboardFiles(context.Background(), &ListPluginDashboardFilesArgs{
|
||||
PluginID: "pluginWithDashboards",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
require.Len(t, res.FileReferences, 2)
|
||||
})
|
||||
|
||||
t.Run("With filesystem", func(t *testing.T) {
|
||||
origOpenDashboardFile := openDashboardFile
|
||||
mapFs := fstest.MapFS{
|
||||
"dashboards/dash1.json": {
|
||||
Data: []byte("dash1"),
|
||||
},
|
||||
"dashboards/dash2.json": {
|
||||
Data: []byte("dash2"),
|
||||
},
|
||||
"dashboards/dash3.json": {
|
||||
Data: []byte("dash3"),
|
||||
},
|
||||
"dash2.json": {
|
||||
Data: []byte("dash2"),
|
||||
},
|
||||
}
|
||||
openDashboardFile = func(ctx context.Context, pluginFiles plugins.FileStore, pluginID, name string) (*plugins.File, error) {
|
||||
f, err := mapFs.Open(name)
|
||||
require.NoError(t, err)
|
||||
|
||||
b, err := io.ReadAll(f)
|
||||
require.NoError(t, err)
|
||||
return &plugins.File{Content: b}, nil
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
openDashboardFile = origOpenDashboardFile
|
||||
})
|
||||
|
||||
t.Run("Should return file not found error when trying to get non-existing plugin dashboard file content", func(t *testing.T) {
|
||||
res, err := m.GetPluginDashboardFileContents(context.Background(), &GetPluginDashboardFileContentsArgs{
|
||||
PluginID: "pluginWithDashboards",
|
||||
FileReference: "dashboards/dash3.json",
|
||||
})
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, "plugin dashboard file not found")
|
||||
require.Nil(t, res)
|
||||
})
|
||||
|
||||
t.Run("Should return file content for dashboards/dash1.json", func(t *testing.T) {
|
||||
res, err := m.GetPluginDashboardFileContents(context.Background(), &GetPluginDashboardFileContentsArgs{
|
||||
PluginID: "pluginWithDashboards",
|
||||
FileReference: "dashboards/dash1.json",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
require.Equal(t, "dash1", string(res.Content))
|
||||
})
|
||||
|
||||
t.Run("Should return file content for dashboards/dash2.json", func(t *testing.T) {
|
||||
res, err := m.GetPluginDashboardFileContents(context.Background(), &GetPluginDashboardFileContentsArgs{
|
||||
PluginID: "pluginWithDashboards",
|
||||
FileReference: "dashboards/dash2.json",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
require.Equal(t, "dash2", string(res.Content))
|
||||
})
|
||||
|
||||
t.Run("Should return error when trying to read relative file", func(t *testing.T) {
|
||||
res, err := m.GetPluginDashboardFileContents(context.Background(), &GetPluginDashboardFileContentsArgs{
|
||||
PluginID: "pluginWithDashboards",
|
||||
FileReference: "dashboards/../dash2.json",
|
||||
})
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, "plugin dashboard file not found")
|
||||
require.Nil(t, res)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func setupPluginDashboardsForTest(t *testing.T) *FileStoreManager {
|
||||
t.Helper()
|
||||
|
||||
p1 := &plugins.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "pluginWithoutDashboards",
|
||||
Includes: []*plugins.Includes{
|
||||
{
|
||||
Type: "page",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
p2 := &plugins.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "pluginWithDashboards",
|
||||
Includes: []*plugins.Includes{
|
||||
{
|
||||
Type: "page",
|
||||
},
|
||||
{
|
||||
Type: "dashboard",
|
||||
Path: "dashboards/dash1.json",
|
||||
},
|
||||
{
|
||||
Type: "dashboard",
|
||||
Path: "dashboards/dash2.json",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return &FileStoreManager{
|
||||
pluginStore: &pluginstore.FakePluginStore{
|
||||
PluginList: []pluginstore.Plugin{pluginstore.ToGrafanaDTO(p1), pluginstore.ToGrafanaDTO(p2)},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package dashboards
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// FileStore is the interface for plugin dashboard file storage.
|
||||
type FileStore interface {
|
||||
// ListPluginDashboardFiles lists plugin dashboard files.
|
||||
ListPluginDashboardFiles(ctx context.Context, args *ListPluginDashboardFilesArgs) (*ListPluginDashboardFilesResult, error)
|
||||
// GetPluginDashboardFileContents gets the referenced plugin dashboard file content.
|
||||
GetPluginDashboardFileContents(ctx context.Context, args *GetPluginDashboardFileContentsArgs) (*GetPluginDashboardFileContentsResult, error)
|
||||
}
|
||||
|
||||
// ListPluginDashboardFilesArgs list plugin dashboard files argument model.
|
||||
type ListPluginDashboardFilesArgs struct {
|
||||
PluginID string
|
||||
}
|
||||
|
||||
// ListPluginDashboardFilesResult list plugin dashboard files result model.
|
||||
type ListPluginDashboardFilesResult struct {
|
||||
FileReferences []string
|
||||
}
|
||||
|
||||
// GetPluginDashboardFileContentsArgs get plugin dashboard file content argument model.
|
||||
type GetPluginDashboardFileContentsArgs struct {
|
||||
PluginID string
|
||||
FileReference string
|
||||
}
|
||||
|
||||
// GetPluginDashboardFileContentsResult get plugin dashboard file content result model.
|
||||
type GetPluginDashboardFileContentsResult struct {
|
||||
Content []byte
|
||||
}
|
||||
@@ -10,16 +10,16 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/adapters"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
)
|
||||
|
||||
var ErrPluginNotFound = errors.New("plugin not found")
|
||||
|
||||
func ProvideService(cacheService *localcache.CacheService, pluginStore plugins.Store,
|
||||
func ProvideService(cacheService *localcache.CacheService, pluginStore pluginstore.Store,
|
||||
dataSourceService datasources.DataSourceService, pluginSettingsService pluginsettings.Service) *Provider {
|
||||
return &Provider{
|
||||
cacheService: cacheService,
|
||||
@@ -31,7 +31,7 @@ func ProvideService(cacheService *localcache.CacheService, pluginStore plugins.S
|
||||
|
||||
type Provider struct {
|
||||
cacheService *localcache.CacheService
|
||||
pluginStore plugins.Store
|
||||
pluginStore pluginstore.Store
|
||||
dataSourceService datasources.DataSourceService
|
||||
pluginSettingsService pluginsettings.Service
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/registry"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/store"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/searchV2"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/tsdb/azuremonitor"
|
||||
@@ -134,7 +134,7 @@ func verifyPluginQuery(t *testing.T, ctx context.Context, c plugins.Client) {
|
||||
require.JSONEq(t, `{"results":{"A":{"frames":[{"schema":{"refId":"A","fields":[{"name":"time","type":"time","typeInfo":{"frame":"time.Time"}},{"name":"A-series","type":"number","typeInfo":{"frame":"int64","nullable":true}}]},"data":{"values":[[1661420570000,1661420630000,1661420690000,1661420750000,1661420810000,1661420870000],[1,20,90,30,5,0]]}}],"status":200}}}`, string(payload))
|
||||
}
|
||||
|
||||
func verifyCorePluginCatalogue(t *testing.T, ctx context.Context, ps *store.Service) {
|
||||
func verifyCorePluginCatalogue(t *testing.T, ctx context.Context, ps *pluginstore.Service) {
|
||||
t.Helper()
|
||||
|
||||
expPanels := map[string]struct{}{
|
||||
@@ -207,7 +207,7 @@ func verifyCorePluginCatalogue(t *testing.T, ctx context.Context, ps *store.Serv
|
||||
require.Equal(t, len(expPanels), len(panels))
|
||||
for _, p := range panels {
|
||||
p, exists := ps.Plugin(ctx, p.ID)
|
||||
require.NotEqual(t, plugins.PluginDTO{}, p)
|
||||
require.NotEqual(t, pluginstore.Plugin{}, p)
|
||||
require.True(t, exists)
|
||||
require.Contains(t, expPanels, p.ID)
|
||||
}
|
||||
@@ -216,7 +216,7 @@ func verifyCorePluginCatalogue(t *testing.T, ctx context.Context, ps *store.Serv
|
||||
require.Equal(t, len(expDataSources), len(dataSources))
|
||||
for _, ds := range dataSources {
|
||||
p, exists := ps.Plugin(ctx, ds.ID)
|
||||
require.NotEqual(t, plugins.PluginDTO{}, p)
|
||||
require.NotEqual(t, pluginstore.Plugin{}, p)
|
||||
require.True(t, exists)
|
||||
require.Contains(t, expDataSources, ds.ID)
|
||||
}
|
||||
@@ -233,7 +233,7 @@ func verifyCorePluginCatalogue(t *testing.T, ctx context.Context, ps *store.Serv
|
||||
require.Equal(t, len(expPanels)+len(expDataSources)+len(expApps), len(ps.Plugins(ctx)))
|
||||
}
|
||||
|
||||
func verifyBundledPlugins(t *testing.T, ctx context.Context, ps *store.Service) {
|
||||
func verifyBundledPlugins(t *testing.T, ctx context.Context, ps *pluginstore.Service) {
|
||||
t.Helper()
|
||||
|
||||
dsPlugins := make(map[string]struct{})
|
||||
@@ -243,7 +243,7 @@ func verifyBundledPlugins(t *testing.T, ctx context.Context, ps *store.Service)
|
||||
|
||||
inputPlugin, exists := ps.Plugin(ctx, "input")
|
||||
require.True(t, exists)
|
||||
require.NotEqual(t, plugins.PluginDTO{}, inputPlugin)
|
||||
require.NotEqual(t, pluginstore.Plugin{}, inputPlugin)
|
||||
require.NotNil(t, dsPlugins["input"])
|
||||
|
||||
pluginRoutes := make(map[string]*plugins.StaticRoute)
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/registry"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/signature"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/sources"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/store"
|
||||
"github.com/grafana/grafana/pkg/plugins/oauth"
|
||||
"github.com/grafana/grafana/pkg/plugins/pluginscdn"
|
||||
"github.com/grafana/grafana/pkg/plugins/repo"
|
||||
@@ -46,6 +45,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
pluginSettings "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings/service"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/serviceregistration"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
@@ -53,11 +53,11 @@ import (
|
||||
// WireSet provides a wire.ProviderSet of plugin providers.
|
||||
var WireSet = wire.NewSet(
|
||||
config.ProvideConfig,
|
||||
store.ProvideService,
|
||||
wire.Bind(new(plugins.Store), new(*store.Service)),
|
||||
wire.Bind(new(plugins.RendererManager), new(*store.Service)),
|
||||
wire.Bind(new(plugins.SecretsPluginManager), new(*store.Service)),
|
||||
wire.Bind(new(plugins.StaticRouteResolver), new(*store.Service)),
|
||||
pluginstore.ProvideService,
|
||||
wire.Bind(new(pluginstore.Store), new(*pluginstore.Service)),
|
||||
wire.Bind(new(plugins.RendererManager), new(*pluginstore.Service)),
|
||||
wire.Bind(new(plugins.SecretsPluginManager), new(*pluginstore.Service)),
|
||||
wire.Bind(new(plugins.StaticRouteResolver), new(*pluginstore.Service)),
|
||||
ProvideClientDecorator,
|
||||
wire.Bind(new(plugins.Client), new(*client.Decorator)),
|
||||
process.ProvideService,
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package pluginstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
)
|
||||
|
||||
type FakePluginStore struct {
|
||||
PluginList []Plugin
|
||||
}
|
||||
|
||||
func (pr *FakePluginStore) Plugin(_ context.Context, pluginID string) (Plugin, bool) {
|
||||
for _, v := range pr.PluginList {
|
||||
if v.ID == pluginID {
|
||||
return v, true
|
||||
}
|
||||
}
|
||||
|
||||
return Plugin{}, false
|
||||
}
|
||||
|
||||
func (pr *FakePluginStore) Plugins(_ context.Context, pluginTypes ...plugins.Type) []Plugin {
|
||||
var result []Plugin
|
||||
if len(pluginTypes) == 0 {
|
||||
pluginTypes = plugins.PluginTypes
|
||||
}
|
||||
|
||||
for _, v := range pr.PluginList {
|
||||
for _, t := range pluginTypes {
|
||||
if v.Type == t {
|
||||
result = append(result, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package pluginstore
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
)
|
||||
|
||||
type Plugin struct {
|
||||
plugins.JSONData
|
||||
|
||||
fs plugins.FS
|
||||
supportsStreaming bool
|
||||
|
||||
Class plugins.Class
|
||||
|
||||
// App fields
|
||||
IncludedInAppID string
|
||||
DefaultNavURL string
|
||||
Pinned bool
|
||||
|
||||
// Signature fields
|
||||
Signature plugins.SignatureStatus
|
||||
SignatureType plugins.SignatureType
|
||||
SignatureOrg string
|
||||
SignatureError *plugins.SignatureError
|
||||
|
||||
// SystemJS fields
|
||||
Module string
|
||||
BaseURL string
|
||||
|
||||
AngularDetected bool
|
||||
|
||||
// This will be moved to plugin.json when we have general support in gcom
|
||||
Alias string `json:"alias,omitempty"`
|
||||
}
|
||||
|
||||
func (p Plugin) SupportsStreaming() bool {
|
||||
return p.supportsStreaming
|
||||
}
|
||||
|
||||
func (p Plugin) Base() string {
|
||||
return p.fs.Base()
|
||||
}
|
||||
|
||||
func (p Plugin) IsApp() bool {
|
||||
return p.Type == plugins.TypeApp
|
||||
}
|
||||
|
||||
func (p Plugin) IsCorePlugin() bool {
|
||||
return p.Class == plugins.ClassCore
|
||||
}
|
||||
|
||||
func ToGrafanaDTO(p *plugins.Plugin) Plugin {
|
||||
supportsStreaming := false
|
||||
pc, exists := p.Client()
|
||||
if exists && pc != nil && pc.(backend.StreamHandler) != nil {
|
||||
supportsStreaming = false
|
||||
}
|
||||
|
||||
return Plugin{
|
||||
fs: p.FS,
|
||||
supportsStreaming: supportsStreaming,
|
||||
Class: p.Class,
|
||||
JSONData: p.JSONData,
|
||||
IncludedInAppID: p.IncludedInAppID,
|
||||
DefaultNavURL: p.DefaultNavURL,
|
||||
Pinned: p.Pinned,
|
||||
Signature: p.Signature,
|
||||
SignatureType: p.SignatureType,
|
||||
SignatureOrg: p.SignatureOrg,
|
||||
SignatureError: p.SignatureError,
|
||||
Module: p.Module,
|
||||
BaseURL: p.BaseURL,
|
||||
AngularDetected: p.AngularDetected,
|
||||
Alias: p.Alias,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package pluginstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/loader"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/registry"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/sources"
|
||||
)
|
||||
|
||||
var _ Store = (*Service)(nil)
|
||||
|
||||
// Store is the publicly accessible storage for plugins.
|
||||
type Store interface {
|
||||
// Plugin finds a plugin by its ID.
|
||||
Plugin(ctx context.Context, pluginID string) (Plugin, bool)
|
||||
// Plugins returns plugins by their requested type.
|
||||
Plugins(ctx context.Context, pluginTypes ...plugins.Type) []Plugin
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
pluginRegistry registry.Service
|
||||
pluginLoader loader.Service
|
||||
}
|
||||
|
||||
func ProvideService(pluginRegistry registry.Service, pluginSources sources.Registry,
|
||||
pluginLoader loader.Service) (*Service, error) {
|
||||
ctx := context.Background()
|
||||
for _, ps := range pluginSources.List(ctx) {
|
||||
if _, err := pluginLoader.Load(ctx, ps); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return New(pluginRegistry, pluginLoader), nil
|
||||
}
|
||||
|
||||
func (s *Service) Run(ctx context.Context) error {
|
||||
<-ctx.Done()
|
||||
s.shutdown(ctx)
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
func New(pluginRegistry registry.Service, pluginLoader loader.Service) *Service {
|
||||
return &Service{
|
||||
pluginRegistry: pluginRegistry,
|
||||
pluginLoader: pluginLoader,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) Plugin(ctx context.Context, pluginID string) (Plugin, bool) {
|
||||
p, exists := s.plugin(ctx, pluginID)
|
||||
if !exists {
|
||||
return Plugin{}, false
|
||||
}
|
||||
|
||||
return ToGrafanaDTO(p), true
|
||||
}
|
||||
|
||||
func (s *Service) Plugins(ctx context.Context, pluginTypes ...plugins.Type) []Plugin {
|
||||
// if no types passed, assume all
|
||||
if len(pluginTypes) == 0 {
|
||||
pluginTypes = plugins.PluginTypes
|
||||
}
|
||||
|
||||
var requestedTypes = make(map[plugins.Type]struct{})
|
||||
for _, pt := range pluginTypes {
|
||||
requestedTypes[pt] = struct{}{}
|
||||
}
|
||||
|
||||
pluginsList := make([]Plugin, 0)
|
||||
for _, p := range s.availablePlugins(ctx) {
|
||||
if _, exists := requestedTypes[p.Type]; exists {
|
||||
pluginsList = append(pluginsList, ToGrafanaDTO(p))
|
||||
}
|
||||
}
|
||||
return pluginsList
|
||||
}
|
||||
|
||||
func (s *Service) Renderer(ctx context.Context) *plugins.Plugin {
|
||||
for _, p := range s.availablePlugins(ctx) {
|
||||
if p.IsRenderer() {
|
||||
return p
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) SecretsManager(ctx context.Context) *plugins.Plugin {
|
||||
for _, p := range s.availablePlugins(ctx) {
|
||||
if p.IsSecretsManager() {
|
||||
return p
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// plugin finds a plugin with `pluginID` from the registry that is not decommissioned
|
||||
func (s *Service) plugin(ctx context.Context, pluginID string) (*plugins.Plugin, bool) {
|
||||
p, exists := s.pluginRegistry.Plugin(ctx, pluginID)
|
||||
if !exists {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if p.IsDecommissioned() {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return p, true
|
||||
}
|
||||
|
||||
// availablePlugins returns all non-decommissioned plugins from the registry sorted by alphabetic order on `plugin.ID`
|
||||
func (s *Service) availablePlugins(ctx context.Context) []*plugins.Plugin {
|
||||
ps := s.pluginRegistry.Plugins(ctx)
|
||||
|
||||
res := make([]*plugins.Plugin, 0, len(ps))
|
||||
for _, p := range ps {
|
||||
if !p.IsDecommissioned() {
|
||||
res = append(res, p)
|
||||
}
|
||||
}
|
||||
sort.SliceStable(res, func(i, j int) bool {
|
||||
return res[i].ID < res[j].ID
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
func (s *Service) Routes(ctx context.Context) []*plugins.StaticRoute {
|
||||
staticRoutes := make([]*plugins.StaticRoute, 0)
|
||||
|
||||
for _, p := range s.availablePlugins(ctx) {
|
||||
if p.StaticRoute() != nil {
|
||||
staticRoutes = append(staticRoutes, p.StaticRoute())
|
||||
}
|
||||
}
|
||||
return staticRoutes
|
||||
}
|
||||
|
||||
func (s *Service) shutdown(ctx context.Context) {
|
||||
var wg sync.WaitGroup
|
||||
for _, plugin := range s.pluginRegistry.Plugins(ctx) {
|
||||
wg.Add(1)
|
||||
go func(ctx context.Context, p *plugins.Plugin) {
|
||||
defer wg.Done()
|
||||
p.Logger().Debug("Stopping plugin")
|
||||
if _, err := s.pluginLoader.Unload(ctx, p); err != nil {
|
||||
p.Logger().Error("Failed to stop plugin", "error", err)
|
||||
}
|
||||
p.Logger().Debug("Plugin stopped")
|
||||
}(ctx, plugin)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
package pluginstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"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/plugins/manager/fakes"
|
||||
)
|
||||
|
||||
func TestStore_ProvideService(t *testing.T) {
|
||||
t.Run("Plugin sources are added in order", func(t *testing.T) {
|
||||
var addedPaths []string
|
||||
l := &fakes.FakeLoader{
|
||||
LoadFunc: func(ctx context.Context, src plugins.PluginSource) ([]*plugins.Plugin, error) {
|
||||
addedPaths = append(addedPaths, src.PluginURIs(ctx)...)
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
|
||||
srcs := &fakes.FakeSourceRegistry{ListFunc: func(_ context.Context) []plugins.PluginSource {
|
||||
return []plugins.PluginSource{
|
||||
&fakes.FakePluginSource{
|
||||
PluginClassFunc: func(ctx context.Context) plugins.Class {
|
||||
return plugins.ClassBundled
|
||||
},
|
||||
PluginURIsFunc: func(ctx context.Context) []string {
|
||||
return []string{"path1"}
|
||||
},
|
||||
},
|
||||
&fakes.FakePluginSource{
|
||||
PluginClassFunc: func(ctx context.Context) plugins.Class {
|
||||
return plugins.ClassExternal
|
||||
},
|
||||
PluginURIsFunc: func(ctx context.Context) []string {
|
||||
return []string{"path2", "path3"}
|
||||
},
|
||||
},
|
||||
}
|
||||
}}
|
||||
|
||||
_, err := ProvideService(fakes.NewFakePluginRegistry(), srcs, l)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []string{"path1", "path2", "path3"}, addedPaths)
|
||||
})
|
||||
}
|
||||
|
||||
func TestStore_Plugin(t *testing.T) {
|
||||
t.Run("Plugin returns all non-decommissioned plugins", func(t *testing.T) {
|
||||
p1 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-datasource"}}
|
||||
p1.RegisterClient(&DecommissionedPlugin{})
|
||||
p2 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-panel"}}
|
||||
|
||||
ps := New(&fakes.FakePluginRegistry{
|
||||
Store: map[string]*plugins.Plugin{
|
||||
p1.ID: p1,
|
||||
p2.ID: p2,
|
||||
},
|
||||
}, &fakes.FakeLoader{})
|
||||
|
||||
p, exists := ps.Plugin(context.Background(), p1.ID)
|
||||
require.False(t, exists)
|
||||
require.Equal(t, Plugin{}, p)
|
||||
|
||||
p, exists = ps.Plugin(context.Background(), p2.ID)
|
||||
require.True(t, exists)
|
||||
require.Equal(t, p, ToGrafanaDTO(p2))
|
||||
})
|
||||
}
|
||||
|
||||
func TestStore_Plugins(t *testing.T) {
|
||||
t.Run("Plugin returns all non-decommissioned plugins by type", func(t *testing.T) {
|
||||
p1 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "a-test-datasource", Type: plugins.TypeDataSource}}
|
||||
p2 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "b-test-panel", Type: plugins.TypePanel}}
|
||||
p3 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "c-test-panel", Type: plugins.TypePanel}}
|
||||
p4 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "d-test-app", Type: plugins.TypeApp}}
|
||||
p5 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "e-test-panel", Type: plugins.TypePanel}}
|
||||
p5.RegisterClient(&DecommissionedPlugin{})
|
||||
|
||||
ps := New(&fakes.FakePluginRegistry{
|
||||
Store: map[string]*plugins.Plugin{
|
||||
p1.ID: p1,
|
||||
p2.ID: p2,
|
||||
p3.ID: p3,
|
||||
p4.ID: p4,
|
||||
p5.ID: p5,
|
||||
},
|
||||
}, &fakes.FakeLoader{})
|
||||
|
||||
ToGrafanaDTO(p1)
|
||||
pss := ps.Plugins(context.Background())
|
||||
require.Equal(t, pss, []Plugin{
|
||||
ToGrafanaDTO(p1), ToGrafanaDTO(p2),
|
||||
ToGrafanaDTO(p3), ToGrafanaDTO(p4),
|
||||
})
|
||||
|
||||
pss = ps.Plugins(context.Background(), plugins.TypeApp)
|
||||
require.Equal(t, pss, []Plugin{ToGrafanaDTO(p4)})
|
||||
|
||||
pss = ps.Plugins(context.Background(), plugins.TypePanel)
|
||||
require.Equal(t, pss, []Plugin{ToGrafanaDTO(p2), ToGrafanaDTO(p3)})
|
||||
|
||||
pss = ps.Plugins(context.Background(), plugins.TypeDataSource)
|
||||
require.Equal(t, pss, []Plugin{ToGrafanaDTO(p1)})
|
||||
|
||||
pss = ps.Plugins(context.Background(), plugins.TypeDataSource, plugins.TypeApp, plugins.TypePanel)
|
||||
require.Equal(t, pss, []Plugin{
|
||||
ToGrafanaDTO(p1), ToGrafanaDTO(p2),
|
||||
ToGrafanaDTO(p3), ToGrafanaDTO(p4),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestStore_Routes(t *testing.T) {
|
||||
t.Run("Routes returns all static routes for non-decommissioned plugins", func(t *testing.T) {
|
||||
p1 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "a-test-renderer", Type: plugins.TypeRenderer}, FS: fakes.NewFakePluginFiles("/some/dir")}
|
||||
p2 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "b-test-panel", Type: plugins.TypePanel}, FS: fakes.NewFakePluginFiles("/grafana/")}
|
||||
p3 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "c-test-secrets", Type: plugins.TypeSecretsManager}, FS: fakes.NewFakePluginFiles("./secrets"), Class: plugins.ClassCore}
|
||||
p4 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "d-test-datasource", Type: plugins.TypeDataSource}, FS: fakes.NewFakePluginFiles("../test")}
|
||||
p5 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "e-test-app", Type: plugins.TypeApp}, FS: fakes.NewFakePluginFiles("any/path")}
|
||||
p6 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "f-test-app", Type: plugins.TypeApp}}
|
||||
p6.RegisterClient(&DecommissionedPlugin{})
|
||||
|
||||
ps := New(&fakes.FakePluginRegistry{
|
||||
Store: map[string]*plugins.Plugin{
|
||||
p1.ID: p1,
|
||||
p2.ID: p2,
|
||||
p3.ID: p3,
|
||||
p4.ID: p4,
|
||||
p5.ID: p5,
|
||||
p6.ID: p6,
|
||||
},
|
||||
}, &fakes.FakeLoader{})
|
||||
|
||||
sr := func(p *plugins.Plugin) *plugins.StaticRoute {
|
||||
return &plugins.StaticRoute{PluginID: p.ID, Directory: p.FS.Base()}
|
||||
}
|
||||
|
||||
rs := ps.Routes(context.Background())
|
||||
require.Equal(t, []*plugins.StaticRoute{sr(p1), sr(p2), sr(p4), sr(p5)}, rs)
|
||||
})
|
||||
}
|
||||
|
||||
func TestStore_Renderer(t *testing.T) {
|
||||
t.Run("Renderer returns a single (non-decommissioned) renderer plugin", func(t *testing.T) {
|
||||
p1 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-renderer", Type: plugins.TypeRenderer}}
|
||||
p2 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-panel", Type: plugins.TypePanel}}
|
||||
p3 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-app", Type: plugins.TypeApp}}
|
||||
|
||||
ps := New(&fakes.FakePluginRegistry{
|
||||
Store: map[string]*plugins.Plugin{
|
||||
p1.ID: p1,
|
||||
p2.ID: p2,
|
||||
p3.ID: p3,
|
||||
},
|
||||
}, &fakes.FakeLoader{})
|
||||
|
||||
r := ps.Renderer(context.Background())
|
||||
require.Equal(t, p1, r)
|
||||
})
|
||||
}
|
||||
|
||||
func TestStore_SecretsManager(t *testing.T) {
|
||||
t.Run("Renderer returns a single (non-decommissioned) secrets manager plugin", func(t *testing.T) {
|
||||
p1 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-renderer", Type: plugins.TypeRenderer}}
|
||||
p2 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-panel", Type: plugins.TypePanel}}
|
||||
p3 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-secrets", Type: plugins.TypeSecretsManager}}
|
||||
p4 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-datasource", Type: plugins.TypeDataSource}}
|
||||
|
||||
ps := New(&fakes.FakePluginRegistry{
|
||||
Store: map[string]*plugins.Plugin{
|
||||
p1.ID: p1,
|
||||
p2.ID: p2,
|
||||
p3.ID: p3,
|
||||
p4.ID: p4,
|
||||
},
|
||||
}, &fakes.FakeLoader{})
|
||||
|
||||
r := ps.SecretsManager(context.Background())
|
||||
require.Equal(t, p3, r)
|
||||
})
|
||||
}
|
||||
|
||||
func TestProcessManager_shutdown(t *testing.T) {
|
||||
p := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-datasource", Type: plugins.TypeDataSource}} // Backend: true
|
||||
backend := &fakes.FakeBackendPlugin{}
|
||||
p.RegisterClient(backend)
|
||||
p.SetLogger(log.NewTestLogger())
|
||||
|
||||
unloaded := false
|
||||
ps := New(&fakes.FakePluginRegistry{
|
||||
Store: map[string]*plugins.Plugin{
|
||||
p.ID: p,
|
||||
},
|
||||
}, &fakes.FakeLoader{
|
||||
UnloadFunc: func(_ context.Context, plugin *plugins.Plugin) (*plugins.Plugin, error) {
|
||||
require.Equal(t, p, plugin)
|
||||
unloaded = true
|
||||
return nil, nil
|
||||
},
|
||||
})
|
||||
|
||||
pCtx := context.Background()
|
||||
cCtx, cancel := context.WithCancel(pCtx)
|
||||
var wgRun sync.WaitGroup
|
||||
wgRun.Add(1)
|
||||
var runErr error
|
||||
go func() {
|
||||
runErr = ps.Run(cCtx)
|
||||
wgRun.Done()
|
||||
}()
|
||||
|
||||
t.Run("When context is cancelled the plugin is stopped", func(t *testing.T) {
|
||||
cancel()
|
||||
wgRun.Wait()
|
||||
require.ErrorIs(t, runErr, context.Canceled)
|
||||
require.True(t, unloaded)
|
||||
})
|
||||
}
|
||||
|
||||
func TestStore_availablePlugins(t *testing.T) {
|
||||
t.Run("Decommissioned plugins are excluded from availablePlugins", func(t *testing.T) {
|
||||
p1 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-datasource"}}
|
||||
p1.RegisterClient(&DecommissionedPlugin{})
|
||||
p2 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-app"}}
|
||||
|
||||
ps := New(&fakes.FakePluginRegistry{
|
||||
Store: map[string]*plugins.Plugin{
|
||||
p1.ID: p1,
|
||||
p2.ID: p2,
|
||||
},
|
||||
}, &fakes.FakeLoader{})
|
||||
|
||||
aps := ps.availablePlugins(context.Background())
|
||||
require.Len(t, aps, 1)
|
||||
require.Equal(t, p2, aps[0])
|
||||
})
|
||||
}
|
||||
|
||||
type DecommissionedPlugin struct {
|
||||
backendplugin.Plugin
|
||||
}
|
||||
|
||||
func (p *DecommissionedPlugin) Decommission() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *DecommissionedPlugin) IsDecommissioned() bool {
|
||||
return true
|
||||
}
|
||||
@@ -26,18 +26,18 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/signature"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/signature/statickey"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/sources"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/store"
|
||||
"github.com/grafana/grafana/pkg/plugins/pluginscdn"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/config"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pipeline"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
type IntegrationTestCtx struct {
|
||||
PluginClient plugins.Client
|
||||
PluginStore *store.Service
|
||||
PluginStore *pluginstore.Service
|
||||
PluginRegistry registry.Service
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ func CreateIntegrationTestCtx(t *testing.T, cfg *setting.Cfg, coreRegistry *core
|
||||
Terminator: term,
|
||||
})
|
||||
|
||||
ps, err := store.ProvideService(reg, sources.ProvideService(cfg, pCfg), l)
|
||||
ps, err := pluginstore.ProvideService(reg, sources.ProvideService(cfg, pCfg), l)
|
||||
require.NoError(t, err)
|
||||
|
||||
return &IntegrationTestCtx{
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
)
|
||||
|
||||
type configReader interface {
|
||||
@@ -20,10 +20,10 @@ type configReader interface {
|
||||
|
||||
type configReaderImpl struct {
|
||||
log log.Logger
|
||||
pluginStore plugins.Store
|
||||
pluginStore pluginstore.Store
|
||||
}
|
||||
|
||||
func newConfigReader(logger log.Logger, pluginStore plugins.Store) configReader {
|
||||
func newConfigReader(logger log.Logger, pluginStore pluginstore.Store) configReader {
|
||||
return &configReaderImpl{log: logger, pluginStore: pluginStore}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -34,7 +34,7 @@ func TestConfigReader(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Unknown app plugin should return error", func(t *testing.T) {
|
||||
cfgProvider := newConfigReader(log.New("test logger"), &fakes.FakePluginStore{})
|
||||
cfgProvider := newConfigReader(log.New("test logger"), &pluginstore.FakePluginStore{})
|
||||
_, err := cfgProvider.readConfig(context.Background(), unknownApp)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, "plugin not installed: \"nonexisting\"", err.Error())
|
||||
@@ -48,8 +48,8 @@ func TestConfigReader(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Can read correct properties", func(t *testing.T) {
|
||||
pm := &fakes.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{
|
||||
pm := &pluginstore.FakePluginStore{
|
||||
PluginList: []pluginstore.Plugin{
|
||||
{JSONData: plugins.JSONData{ID: "test-plugin"}},
|
||||
{JSONData: plugins.JSONData{ID: "test-plugin-2"}},
|
||||
},
|
||||
|
||||
@@ -5,14 +5,14 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
)
|
||||
|
||||
// Provision scans a directory for provisioning config files
|
||||
// and provisions the app in those files.
|
||||
func Provision(ctx context.Context, configDirectory string, pluginStore plugins.Store, pluginSettings pluginsettings.Service, orgService org.Service) error {
|
||||
func Provision(ctx context.Context, configDirectory string, pluginStore pluginstore.Store, pluginSettings pluginsettings.Service, orgService org.Service) error {
|
||||
logger := log.New("provisioning.plugins")
|
||||
ap := PluginProvisioner{
|
||||
log: logger,
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
plugifaces "github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
@@ -22,6 +21,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
prov_alerting "github.com/grafana/grafana/pkg/services/provisioning/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/provisioning/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/provisioning/datasources"
|
||||
@@ -37,7 +37,7 @@ func ProvideService(
|
||||
ac accesscontrol.AccessControl,
|
||||
cfg *setting.Cfg,
|
||||
sqlStore db.DB,
|
||||
pluginStore plugifaces.Store,
|
||||
pluginStore pluginstore.Store,
|
||||
encryptionService encryption.Internal,
|
||||
notificatonService *notifications.NotificationService,
|
||||
dashboardProvisioningService dashboardservice.DashboardProvisioningService,
|
||||
@@ -108,7 +108,7 @@ func newProvisioningServiceImpl(
|
||||
newDashboardProvisioner dashboards.DashboardProvisionerFactory,
|
||||
provisionNotifiers func(context.Context, string, notifiers.Manager, org.Service, encryption.Internal, *notifications.NotificationService) error,
|
||||
provisionDatasources func(context.Context, string, datasources.Store, datasources.CorrelationsStore, org.Service) error,
|
||||
provisionPlugins func(context.Context, string, plugifaces.Store, pluginsettings.Service, org.Service) error,
|
||||
provisionPlugins func(context.Context, string, pluginstore.Store, pluginsettings.Service, org.Service) error,
|
||||
) *ProvisioningServiceImpl {
|
||||
return &ProvisioningServiceImpl{
|
||||
log: log.New("provisioning"),
|
||||
@@ -124,7 +124,7 @@ type ProvisioningServiceImpl struct {
|
||||
SQLStore db.DB
|
||||
orgService org.Service
|
||||
ac accesscontrol.AccessControl
|
||||
pluginStore plugifaces.Store
|
||||
pluginStore pluginstore.Store
|
||||
EncryptionService encryption.Internal
|
||||
NotificationService *notifications.NotificationService
|
||||
log log.Logger
|
||||
@@ -133,7 +133,7 @@ type ProvisioningServiceImpl struct {
|
||||
dashboardProvisioner dashboards.DashboardProvisioner
|
||||
provisionNotifiers func(context.Context, string, notifiers.Manager, org.Service, encryption.Internal, *notifications.NotificationService) error
|
||||
provisionDatasources func(context.Context, string, datasources.Store, datasources.CorrelationsStore, org.Service) error
|
||||
provisionPlugins func(context.Context, string, plugifaces.Store, pluginsettings.Service, org.Service) error
|
||||
provisionPlugins func(context.Context, string, pluginstore.Store, pluginsettings.Service, org.Service) error
|
||||
provisionAlerting func(context.Context, prov_alerting.ProvisionerConfig) error
|
||||
mutex sync.Mutex
|
||||
dashboardProvisioningService dashboardservice.DashboardProvisioningService
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
pluginFakes "github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
@@ -27,6 +26,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
|
||||
pluginSettings "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings/service"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
||||
"github.com/grafana/grafana/pkg/services/query"
|
||||
fakeSecrets "github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
@@ -119,8 +119,8 @@ func buildQueryDataService(t *testing.T, cs datasources.CacheService, fpc *fakeP
|
||||
}
|
||||
|
||||
ds := &fakeDatasources.FakeDataSourceService{}
|
||||
pCtxProvider := plugincontext.ProvideService(localcache.ProvideService(), &pluginFakes.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{
|
||||
pCtxProvider := plugincontext.ProvideService(localcache.ProvideService(), &pluginstore.FakePluginStore{
|
||||
PluginList: []pluginstore.Plugin{
|
||||
{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "mysql",
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/models/roletype"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
pluginFakes "github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
||||
@@ -34,6 +33,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
|
||||
pluginSettings "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings/service"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
secretskvs "github.com/grafana/grafana/pkg/services/secrets/kvstore"
|
||||
secretsmng "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
@@ -468,8 +468,8 @@ func setup(t *testing.T) *testContext {
|
||||
}
|
||||
|
||||
pCtxProvider := plugincontext.ProvideService(
|
||||
localcache.ProvideService(), &pluginFakes.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{
|
||||
localcache.ProvideService(), &pluginstore.FakePluginStore{
|
||||
PluginList: []pluginstore.Plugin{
|
||||
{JSONData: plugins.JSONData{ID: "postgres"}},
|
||||
{JSONData: plugins.JSONData{ID: "testdata"}},
|
||||
{JSONData: plugins.JSONData{ID: "mysql"}},
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
pluginFakes "github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/annotations/annotationstest"
|
||||
"github.com/grafana/grafana/pkg/services/apikey"
|
||||
@@ -31,6 +30,7 @@ import (
|
||||
ngstore "github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/org/orgimpl"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
@@ -484,7 +484,7 @@ func setupEnv(t *testing.T, sqlStore *sqlstore.SQLStore, b bus.Bus, quotaService
|
||||
_, err = ngalert.ProvideService(
|
||||
sqlStore.Cfg, featuremgmt.WithFeatures(), nil, nil, routing.NewRouteRegister(), sqlStore, nil, nil, nil, quotaService,
|
||||
secretsService, nil, m, &foldertest.FakeService{}, &acmock.Mock{}, &dashboards.FakeDashboardService{}, nil, b, &acmock.Mock{},
|
||||
annotationstest.NewFakeAnnotationsRepo(), &pluginFakes.FakePluginStore{}, tracer, ruleStore,
|
||||
annotationstest.NewFakeAnnotationsRepo(), &pluginstore.FakePluginStore{}, tracer, ruleStore,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
_, err = storesrv.ProvideService(sqlStore, featuremgmt.WithFeatures(), sqlStore.Cfg, quotaService, storesrv.ProvideSystemUsersService())
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/appcontext"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/tsdb/grafanads"
|
||||
)
|
||||
|
||||
@@ -23,7 +23,7 @@ type dsVal struct {
|
||||
|
||||
type dsCache struct {
|
||||
ds datasources.DataSourceService
|
||||
pluginStore plugins.Store
|
||||
pluginStore pluginstore.Store
|
||||
cache map[int64]map[string]*dsVal
|
||||
timestamp time.Time // across all orgIDs
|
||||
mu sync.Mutex
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
)
|
||||
|
||||
@@ -31,7 +32,7 @@ type EntityReferenceResolver interface {
|
||||
Resolve(ctx context.Context, ref *entity.EntityExternalReference) (ResolutionInfo, error)
|
||||
}
|
||||
|
||||
func ProvideEntityReferenceResolver(ds datasources.DataSourceService, pluginStore plugins.Store) EntityReferenceResolver {
|
||||
func ProvideEntityReferenceResolver(ds datasources.DataSourceService, pluginStore pluginstore.Store) EntityReferenceResolver {
|
||||
return &standardReferenceResolver{
|
||||
pluginStore: pluginStore,
|
||||
ds: dsCache{
|
||||
@@ -42,7 +43,7 @@ func ProvideEntityReferenceResolver(ds datasources.DataSourceService, pluginStor
|
||||
}
|
||||
|
||||
type standardReferenceResolver struct {
|
||||
pluginStore plugins.Store
|
||||
pluginStore pluginstore.Store
|
||||
ds dsCache
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,9 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/appcontext"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
fakeDatasources "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
@@ -37,15 +36,15 @@ func TestResolver(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
p1 := plugins.PluginDTO{}
|
||||
p2 := plugins.PluginDTO{}
|
||||
p3 := plugins.PluginDTO{}
|
||||
p1 := pluginstore.Plugin{}
|
||||
p2 := pluginstore.Plugin{}
|
||||
p3 := pluginstore.Plugin{}
|
||||
|
||||
p1.ID = "influx"
|
||||
p2.ID = "heatmap"
|
||||
p3.ID = "xyz"
|
||||
pluginStore := &fakes.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{p1, p2, p3},
|
||||
pluginStore := &pluginstore.FakePluginStore{
|
||||
PluginList: []pluginstore.Plugin{p1, p2, p3},
|
||||
}
|
||||
provider := ProvideEntityReferenceResolver(ds, pluginStore)
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/supportbundles"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
@@ -105,7 +106,7 @@ func settingsCollector(settings setting.Provider) supportbundles.Collector {
|
||||
}
|
||||
}
|
||||
|
||||
func pluginInfoCollector(pluginStore plugins.Store, pluginSettings pluginsettings.Service, logger log.Logger) supportbundles.Collector {
|
||||
func pluginInfoCollector(pluginStore pluginstore.Store, pluginSettings pluginsettings.Service, logger log.Logger) supportbundles.Collector {
|
||||
return supportbundles.Collector{
|
||||
UID: "plugins",
|
||||
DisplayName: "Plugin information",
|
||||
|
||||
@@ -11,11 +11,11 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/auth/identity"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/supportbundles"
|
||||
"github.com/grafana/grafana/pkg/services/supportbundles/bundleregistry"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@@ -32,7 +32,7 @@ type Service struct {
|
||||
cfg *setting.Cfg
|
||||
features *featuremgmt.FeatureManager
|
||||
pluginSettings pluginsettings.Service
|
||||
pluginStore plugins.Store
|
||||
pluginStore pluginstore.Store
|
||||
store bundleStore
|
||||
|
||||
log log.Logger
|
||||
@@ -51,7 +51,7 @@ func ProvideService(
|
||||
httpServer *grafanaApi.HTTPServer,
|
||||
kvStore kvstore.KVStore,
|
||||
pluginSettings pluginsettings.Service,
|
||||
pluginStore plugins.Store,
|
||||
pluginStore pluginstore.Store,
|
||||
routeRegister routing.RouteRegister,
|
||||
settings setting.Provider,
|
||||
sql db.DB,
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient/httpclientprovider"
|
||||
"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/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -27,14 +27,14 @@ type PluginsService struct {
|
||||
|
||||
enabled bool
|
||||
grafanaVersion string
|
||||
pluginStore plugins.Store
|
||||
pluginStore pluginstore.Store
|
||||
httpClient httpClient
|
||||
mutex sync.RWMutex
|
||||
log log.Logger
|
||||
tracer tracing.Tracer
|
||||
}
|
||||
|
||||
func ProvidePluginsService(cfg *setting.Cfg, pluginStore plugins.Store, tracer tracing.Tracer) (*PluginsService, error) {
|
||||
func ProvidePluginsService(cfg *setting.Cfg, pluginStore pluginstore.Store, tracer tracing.Tracer) (*PluginsService, error) {
|
||||
logger := log.New("plugins.update.checker")
|
||||
cl, err := httpclient.New(httpclient.Options{
|
||||
Middlewares: []httpclient.Middleware{
|
||||
@@ -180,7 +180,7 @@ func canUpdate(v1, v2 string) bool {
|
||||
return ver1.LessThan(ver2)
|
||||
}
|
||||
|
||||
func (s *PluginsService) pluginIDsCSV(m map[string]plugins.PluginDTO) string {
|
||||
func (s *PluginsService) pluginIDsCSV(m map[string]pluginstore.Plugin) string {
|
||||
ids := make([]string, 0, len(m))
|
||||
for pluginID := range m {
|
||||
ids = append(ids, pluginID)
|
||||
@@ -189,8 +189,8 @@ func (s *PluginsService) pluginIDsCSV(m map[string]plugins.PluginDTO) string {
|
||||
return strings.Join(ids, ",")
|
||||
}
|
||||
|
||||
func (s *PluginsService) pluginsEligibleForVersionCheck(ctx context.Context) map[string]plugins.PluginDTO {
|
||||
result := make(map[string]plugins.PluginDTO)
|
||||
func (s *PluginsService) pluginsEligibleForVersionCheck(ctx context.Context) map[string]pluginstore.Plugin {
|
||||
result := make(map[string]pluginstore.Plugin)
|
||||
for _, p := range s.pluginStore.Plugins(ctx) {
|
||||
if p.IsCorePlugin() {
|
||||
continue
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"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/manager/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
)
|
||||
|
||||
func TestPluginUpdateChecker_HasUpdate(t *testing.T) {
|
||||
@@ -21,8 +21,8 @@ func TestPluginUpdateChecker_HasUpdate(t *testing.T) {
|
||||
availableUpdates: map[string]string{
|
||||
"test-ds": "1.0.0",
|
||||
},
|
||||
pluginStore: &fakes.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{
|
||||
pluginStore: &pluginstore.FakePluginStore{
|
||||
PluginList: []pluginstore.Plugin{
|
||||
{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test-ds",
|
||||
@@ -44,8 +44,8 @@ func TestPluginUpdateChecker_HasUpdate(t *testing.T) {
|
||||
"test-panel": "0.9.0",
|
||||
"test-app": "0.0.1",
|
||||
},
|
||||
pluginStore: &fakes.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{
|
||||
pluginStore: &pluginstore.FakePluginStore{
|
||||
PluginList: []pluginstore.Plugin{
|
||||
{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test-ds",
|
||||
@@ -86,8 +86,8 @@ func TestPluginUpdateChecker_HasUpdate(t *testing.T) {
|
||||
availableUpdates: map[string]string{
|
||||
"test-panel": "0.9.0",
|
||||
},
|
||||
pluginStore: &fakes.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{
|
||||
pluginStore: &pluginstore.FakePluginStore{
|
||||
PluginList: []pluginstore.Plugin{
|
||||
{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test-ds",
|
||||
@@ -129,8 +129,8 @@ func TestPluginUpdateChecker_checkForUpdates(t *testing.T) {
|
||||
availableUpdates: map[string]string{
|
||||
"test-app": "1.0.0",
|
||||
},
|
||||
pluginStore: &fakes.FakePluginStore{
|
||||
PluginList: []plugins.PluginDTO{
|
||||
pluginStore: &pluginstore.FakePluginStore{
|
||||
PluginList: []pluginstore.Plugin{
|
||||
{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test-ds",
|
||||
|
||||
Reference in New Issue
Block a user