PluginManager: Make Plugins, Renderer and DataSources non-global (#31866)
* PluginManager: Make Plugins and DataSources non-global Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Fix integration tests Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Replace outdated command Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * DashboardService: Ensure it gets constructed with necessary parameters Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Fix build Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * DashboardService: Ensure it gets constructed with necessary parameters Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Remove dead code Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Fix test Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Fix test Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Remove FocusConvey Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Fix test Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Remove dead code Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Undo interface changes Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Backend: Move tsdbifaces.RequestHandler to plugins.DataRequestHandler Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Rename to DataSourceCount Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Consolidate dashboard interfaces into one Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Fix tests Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Fix tests Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Fix test Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Fix tests Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Fix tests Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Fix tests Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Fix tests Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> * Fix dashboard integration tests Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
@@ -6,8 +6,10 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/dashboards"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/util/errutil"
|
||||
)
|
||||
|
||||
@@ -22,7 +24,7 @@ type DashboardProvisioner interface {
|
||||
}
|
||||
|
||||
// DashboardProvisionerFactory creates DashboardProvisioners based on input
|
||||
type DashboardProvisionerFactory func(string) (DashboardProvisioner, error)
|
||||
type DashboardProvisionerFactory func(string, dashboards.Store, plugins.DataRequestHandler) (DashboardProvisioner, error)
|
||||
|
||||
// Provisioner is responsible for syncing dashboard from disk to Grafana's database.
|
||||
type Provisioner struct {
|
||||
@@ -32,16 +34,15 @@ type Provisioner struct {
|
||||
}
|
||||
|
||||
// New returns a new DashboardProvisioner
|
||||
func New(configDirectory string) (*Provisioner, error) {
|
||||
func New(configDirectory string, store dashboards.Store, reqHandler plugins.DataRequestHandler) (DashboardProvisioner, error) {
|
||||
logger := log.New("provisioning.dashboard")
|
||||
cfgReader := &configReader{path: configDirectory, log: logger}
|
||||
configs, err := cfgReader.readConfig()
|
||||
|
||||
if err != nil {
|
||||
return nil, errutil.Wrap("Failed to read dashboards config", err)
|
||||
}
|
||||
|
||||
fileReaders, err := getFileReaders(configs, logger)
|
||||
fileReaders, err := getFileReaders(configs, logger, store)
|
||||
if err != nil {
|
||||
return nil, errutil.Wrap("Failed to initialize file readers", err)
|
||||
}
|
||||
@@ -115,13 +116,14 @@ func (provider *Provisioner) GetAllowUIUpdatesFromConfig(name string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func getFileReaders(configs []*config, logger log.Logger) ([]*FileReader, error) {
|
||||
func getFileReaders(configs []*config, logger log.Logger, store dashboards.Store) ([]*FileReader, error) {
|
||||
var readers []*FileReader
|
||||
|
||||
for _, config := range configs {
|
||||
switch config.Type {
|
||||
case "file":
|
||||
fileReader, err := NewDashboardFileReader(config, logger.New("type", config.Type, "name", config.Name))
|
||||
fileReader, err := NewDashboardFileReader(config, logger.New("type", config.Type, "name", config.Name),
|
||||
store)
|
||||
if err != nil {
|
||||
return nil, errutil.Wrapf(err, "Failed to create file reader for config %v", config.Name)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
dboards "github.com/grafana/grafana/pkg/dashboards"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
@@ -35,7 +36,7 @@ type FileReader struct {
|
||||
}
|
||||
|
||||
// NewDashboardFileReader returns a new filereader based on `config`
|
||||
func NewDashboardFileReader(cfg *config, log log.Logger) (*FileReader, error) {
|
||||
func NewDashboardFileReader(cfg *config, log log.Logger, store dboards.Store) (*FileReader, error) {
|
||||
var path string
|
||||
path, ok := cfg.Options["path"].(string)
|
||||
if !ok {
|
||||
@@ -56,7 +57,7 @@ func NewDashboardFileReader(cfg *config, log log.Logger) (*FileReader, error) {
|
||||
Cfg: cfg,
|
||||
Path: path,
|
||||
log: log,
|
||||
dashboardProvisioningService: dashboards.NewProvisioningService(),
|
||||
dashboardProvisioningService: dashboards.NewProvisioningService(store),
|
||||
FoldersFromFilesStructure: foldersFromFilesStructure,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ func TestProvisionedSymlinkedFolder(t *testing.T) {
|
||||
Options: map[string]interface{}{"path": symlinkedFolder},
|
||||
}
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"))
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
want, err := filepath.Abs(containingID)
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
dboards "github.com/grafana/grafana/pkg/dashboards"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@@ -41,14 +42,14 @@ func TestCreatingNewDashboardFileReader(t *testing.T) {
|
||||
|
||||
Convey("using path parameter", func() {
|
||||
cfg.Options["path"] = defaultDashboards
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"))
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(reader.Path, ShouldNotEqual, "")
|
||||
})
|
||||
|
||||
Convey("using folder as options", func() {
|
||||
cfg.Options["folder"] = defaultDashboards
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"))
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(reader.Path, ShouldNotEqual, "")
|
||||
})
|
||||
@@ -56,7 +57,7 @@ func TestCreatingNewDashboardFileReader(t *testing.T) {
|
||||
Convey("using foldersFromFilesStructure as options", func() {
|
||||
cfg.Options["path"] = foldersFromFilesStructure
|
||||
cfg.Options["foldersFromFilesStructure"] = true
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"))
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(reader.Path, ShouldNotEqual, "")
|
||||
})
|
||||
@@ -68,7 +69,7 @@ func TestCreatingNewDashboardFileReader(t *testing.T) {
|
||||
}
|
||||
|
||||
cfg.Options["folder"] = fullPath
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"))
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(reader.Path, ShouldEqual, fullPath)
|
||||
@@ -77,7 +78,7 @@ func TestCreatingNewDashboardFileReader(t *testing.T) {
|
||||
|
||||
Convey("using relative path", func() {
|
||||
cfg.Options["folder"] = defaultDashboards
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"))
|
||||
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
resolvedPath := reader.resolvedPath()
|
||||
@@ -111,7 +112,7 @@ func TestDashboardFileReader(t *testing.T) {
|
||||
cfg.Options["path"] = defaultDashboards
|
||||
cfg.Folder = "Team A"
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger)
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk()
|
||||
@@ -142,7 +143,7 @@ func TestDashboardFileReader(t *testing.T) {
|
||||
Slug: "grafana",
|
||||
})
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger)
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk()
|
||||
@@ -154,7 +155,7 @@ func TestDashboardFileReader(t *testing.T) {
|
||||
Convey("Overrides id from dashboard.json files", func() {
|
||||
cfg.Options["path"] = containingID
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger)
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk()
|
||||
@@ -167,7 +168,7 @@ func TestDashboardFileReader(t *testing.T) {
|
||||
cfg.Options["path"] = foldersFromFilesStructure
|
||||
cfg.Options["foldersFromFilesStructure"] = true
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger)
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk()
|
||||
@@ -211,14 +212,14 @@ func TestDashboardFileReader(t *testing.T) {
|
||||
Folder: "",
|
||||
}
|
||||
|
||||
_, err := NewDashboardFileReader(cfg, logger)
|
||||
_, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("Broken dashboards should not cause error", func() {
|
||||
cfg.Options["path"] = brokenDashboards
|
||||
|
||||
_, err := NewDashboardFileReader(cfg, logger)
|
||||
_, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
@@ -226,13 +227,13 @@ func TestDashboardFileReader(t *testing.T) {
|
||||
cfg1 := &config{Name: "1", Type: "file", OrgID: 1, Folder: "f1", Options: map[string]interface{}{"path": containingID}}
|
||||
cfg2 := &config{Name: "2", Type: "file", OrgID: 1, Folder: "f2", Options: map[string]interface{}{"path": containingID}}
|
||||
|
||||
reader1, err := NewDashboardFileReader(cfg1, logger)
|
||||
reader1, err := NewDashboardFileReader(cfg1, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader1.walkDisk()
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
reader2, err := NewDashboardFileReader(cfg2, logger)
|
||||
reader2, err := NewDashboardFileReader(cfg2, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader2.walkDisk()
|
||||
@@ -336,7 +337,7 @@ func TestDashboardFileReader(t *testing.T) {
|
||||
Convey("Missing dashboard should be unprovisioned if DisableDeletion = true", func() {
|
||||
cfg.DisableDeletion = true
|
||||
|
||||
reader, err := NewDashboardFileReader(cfg, logger)
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk()
|
||||
@@ -347,7 +348,7 @@ func TestDashboardFileReader(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("Missing dashboard should be deleted if DisableDeletion = false", func() {
|
||||
reader, err := NewDashboardFileReader(cfg, logger)
|
||||
reader, err := NewDashboardFileReader(cfg, logger, nil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader.walkDisk()
|
||||
@@ -395,7 +396,7 @@ func mockDashboardProvisioningService() *fakeDashboardProvisioningService {
|
||||
mock := fakeDashboardProvisioningService{
|
||||
provisioned: map[string][]*models.DashboardProvisioning{},
|
||||
}
|
||||
dashboards.NewProvisioningService = func() dashboards.DashboardProvisioningService {
|
||||
dashboards.NewProvisioningService = func(dboards.Store) dashboards.DashboardProvisioningService {
|
||||
return &mock
|
||||
}
|
||||
return &mock
|
||||
|
||||
@@ -55,7 +55,7 @@ func (cr *configReaderImpl) readConfig(path string) ([]*pluginsAsConfig, error)
|
||||
|
||||
checkOrgIDAndOrgName(apps)
|
||||
|
||||
err = validatePluginsConfig(apps)
|
||||
err = cr.validatePluginsConfig(apps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -105,7 +105,7 @@ func validateRequiredField(apps []*pluginsAsConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func validatePluginsConfig(apps []*pluginsAsConfig) error {
|
||||
func (cr *configReaderImpl) validatePluginsConfig(apps []*pluginsAsConfig) error {
|
||||
for i := range apps {
|
||||
if apps[i].Apps == nil {
|
||||
continue
|
||||
|
||||
@@ -6,11 +6,13 @@ import (
|
||||
"sync"
|
||||
|
||||
"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/provisioning/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/provisioning/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/provisioning/notifiers"
|
||||
"github.com/grafana/grafana/pkg/services/provisioning/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util/errutil"
|
||||
)
|
||||
@@ -27,10 +29,8 @@ type ProvisioningService interface {
|
||||
func init() {
|
||||
registry.Register(®istry.Descriptor{
|
||||
Name: "ProvisioningService",
|
||||
Instance: NewProvisioningServiceImpl(
|
||||
func(path string) (dashboards.DashboardProvisioner, error) {
|
||||
return dashboards.New(path)
|
||||
},
|
||||
Instance: newProvisioningServiceImpl(
|
||||
dashboards.New,
|
||||
notifiers.Provision,
|
||||
datasources.Provision,
|
||||
plugins.Provision,
|
||||
@@ -39,7 +39,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
func NewProvisioningServiceImpl(
|
||||
func newProvisioningServiceImpl(
|
||||
newDashboardProvisioner dashboards.DashboardProvisionerFactory,
|
||||
provisionNotifiers func(string) error,
|
||||
provisionDatasources func(string) error,
|
||||
@@ -55,7 +55,9 @@ func NewProvisioningServiceImpl(
|
||||
}
|
||||
|
||||
type provisioningServiceImpl struct {
|
||||
Cfg *setting.Cfg `inject:""`
|
||||
Cfg *setting.Cfg `inject:""`
|
||||
RequestHandler plugifaces.DataRequestHandler `inject:""`
|
||||
SQLStore *sqlstore.SQLStore `inject:""`
|
||||
log log.Logger
|
||||
pollingCtxCancel context.CancelFunc
|
||||
newDashboardProvisioner dashboards.DashboardProvisionerFactory
|
||||
@@ -134,7 +136,7 @@ func (ps *provisioningServiceImpl) ProvisionNotifications() error {
|
||||
|
||||
func (ps *provisioningServiceImpl) ProvisionDashboards() error {
|
||||
dashboardPath := filepath.Join(ps.Cfg.ProvisioningPath, "dashboards")
|
||||
dashProvisioner, err := ps.newDashboardProvisioner(dashboardPath)
|
||||
dashProvisioner, err := ps.newDashboardProvisioner(dashboardPath, ps.SQLStore, ps.RequestHandler)
|
||||
if err != nil {
|
||||
return errutil.Wrap("Failed to create provisioner", err)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
dboards "github.com/grafana/grafana/pkg/dashboards"
|
||||
plugifaces "github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/provisioning/dashboards"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -90,8 +92,8 @@ func setup() *serviceTestStruct {
|
||||
pollChangesChannel <- ctx
|
||||
}
|
||||
|
||||
serviceTest.service = NewProvisioningServiceImpl(
|
||||
func(path string) (dashboards.DashboardProvisioner, error) {
|
||||
serviceTest.service = newProvisioningServiceImpl(
|
||||
func(string, dboards.Store, plugifaces.DataRequestHandler) (dashboards.DashboardProvisioner, error) {
|
||||
return serviceTest.mock, nil
|
||||
},
|
||||
nil,
|
||||
|
||||
Reference in New Issue
Block a user