Chore: Wrap provisioning in dskit service (#71598)

pull/71897/head
Todd Treece 2 years ago committed by GitHub
parent d3ab1c1c1e
commit d280fedb3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      pkg/modules/dependencies.go
  2. 3
      pkg/modules/registry/registry.go
  3. 39
      pkg/server/server.go
  4. 2
      pkg/server/server_test.go
  5. 29
      pkg/services/provisioning/provisioning.go
  6. 13
      pkg/services/provisioning/provisioning_mock.go
  7. 2
      pkg/services/provisioning/provisioning_test.go

@ -11,14 +11,16 @@ const (
GrafanaAPIServer string = "grafana-apiserver" GrafanaAPIServer string = "grafana-apiserver"
// HTTPServer is the HTTP server for Grafana // HTTPServer is the HTTP server for Grafana
HTTPServer string = "http-server" HTTPServer string = "http-server"
// Provisioning sets up Grafana with preconfigured datasources, dashboards, etc.
Provisioning string = "provisioning"
) )
// dependencyMap defines Module Targets => Dependencies // dependencyMap defines Module Targets => Dependencies
var dependencyMap = map[string][]string{ var dependencyMap = map[string][]string{
BackgroundServices: {}, BackgroundServices: {Provisioning, HTTPServer},
CertGenerator: {}, CertGenerator: {},
GrafanaAPIServer: {CertGenerator}, GrafanaAPIServer: {CertGenerator},
All: {BackgroundServices, HTTPServer}, All: {Provisioning, HTTPServer, BackgroundServices},
} }

@ -9,6 +9,7 @@ import (
"github.com/grafana/grafana/pkg/modules" "github.com/grafana/grafana/pkg/modules"
"github.com/grafana/grafana/pkg/server/backgroundsvcs" "github.com/grafana/grafana/pkg/server/backgroundsvcs"
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver" grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
"github.com/grafana/grafana/pkg/services/provisioning"
) )
type Registry interface{} type Registry interface{}
@ -24,6 +25,7 @@ func ProvideRegistry(
backgroundServiceRunner *backgroundsvcs.BackgroundServiceRunner, backgroundServiceRunner *backgroundsvcs.BackgroundServiceRunner,
certGenerator certgenerator.ServiceInterface, certGenerator certgenerator.ServiceInterface,
httpServer *api.HTTPServer, httpServer *api.HTTPServer,
provisioningService *provisioning.ProvisioningServiceImpl,
) *registry { ) *registry {
return newRegistry( return newRegistry(
log.New("modules.registry"), log.New("modules.registry"),
@ -32,6 +34,7 @@ func ProvideRegistry(
backgroundServiceRunner, backgroundServiceRunner,
certGenerator, certGenerator,
httpServer, httpServer,
provisioningService,
) )
} }

@ -19,7 +19,6 @@ import (
moduleRegistry "github.com/grafana/grafana/pkg/modules/registry" moduleRegistry "github.com/grafana/grafana/pkg/modules/registry"
"github.com/grafana/grafana/pkg/registry" "github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/provisioning"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
) )
@ -35,13 +34,12 @@ type Options struct {
// New returns a new instance of Server. // New returns a new instance of Server.
func New(opts Options, cfg *setting.Cfg, httpServer *api.HTTPServer, roleRegistry accesscontrol.RoleRegistry, func New(opts Options, cfg *setting.Cfg, httpServer *api.HTTPServer, roleRegistry accesscontrol.RoleRegistry,
provisioningService provisioning.ProvisioningService,
usageStatsProvidersRegistry registry.UsageStatsProvidersRegistry, statsCollectorService *statscollector.Service, usageStatsProvidersRegistry registry.UsageStatsProvidersRegistry, statsCollectorService *statscollector.Service,
moduleService modules.Engine, moduleService modules.Engine,
_ moduleRegistry.Registry, // imported to invoke initialization via Wire _ moduleRegistry.Registry, // imported to invoke initialization via Wire
) (*Server, error) { ) (*Server, error) {
statsCollectorService.RegisterProviders(usageStatsProvidersRegistry.GetServices()) statsCollectorService.RegisterProviders(usageStatsProvidersRegistry.GetServices())
s, err := newServer(opts, cfg, httpServer, roleRegistry, provisioningService, moduleService) s, err := newServer(opts, cfg, httpServer, roleRegistry, moduleService)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -54,20 +52,18 @@ func New(opts Options, cfg *setting.Cfg, httpServer *api.HTTPServer, roleRegistr
} }
func newServer(opts Options, cfg *setting.Cfg, httpServer *api.HTTPServer, roleRegistry accesscontrol.RoleRegistry, func newServer(opts Options, cfg *setting.Cfg, httpServer *api.HTTPServer, roleRegistry accesscontrol.RoleRegistry,
provisioningService provisioning.ProvisioningService,
moduleService modules.Engine) (*Server, error) { moduleService modules.Engine) (*Server, error) {
return &Server{ return &Server{
HTTPServer: httpServer, HTTPServer: httpServer,
provisioningService: provisioningService, roleRegistry: roleRegistry,
roleRegistry: roleRegistry, shutdownFinished: make(chan struct{}),
shutdownFinished: make(chan struct{}), log: log.New("server"),
log: log.New("server"), cfg: cfg,
cfg: cfg, pidFile: opts.PidFile,
pidFile: opts.PidFile, version: opts.Version,
version: opts.Version, commit: opts.Commit,
commit: opts.Commit, buildBranch: opts.BuildBranch,
buildBranch: opts.BuildBranch, moduleService: moduleService,
moduleService: moduleService,
}, nil }, nil
} }
@ -85,10 +81,9 @@ type Server struct {
commit string commit string
buildBranch string buildBranch string
HTTPServer *api.HTTPServer HTTPServer *api.HTTPServer
roleRegistry accesscontrol.RoleRegistry roleRegistry accesscontrol.RoleRegistry
provisioningService provisioning.ProvisioningService moduleService modules.Engine
moduleService modules.Engine
} }
// init initializes the server and its services. // init initializes the server and its services.
@ -114,11 +109,7 @@ func (s *Server) init(ctx context.Context) error {
return err return err
} }
if err := s.roleRegistry.RegisterFixedRoles(ctx); err != nil { return s.roleRegistry.RegisterFixedRoles(ctx)
return err
}
return s.provisioningService.RunInitProvisioners(ctx)
} }
// Run initializes and starts services. This will block until all services have // Run initializes and starts services. This will block until all services have

@ -15,7 +15,7 @@ import (
func testServer(t *testing.T, m *modules.MockModuleEngine) *Server { func testServer(t *testing.T, m *modules.MockModuleEngine) *Server {
t.Helper() t.Helper()
s, err := newServer(Options{}, setting.NewCfg(), nil, &acimpl.Service{}, nil, m) s, err := newServer(Options{}, setting.NewCfg(), nil, &acimpl.Service{}, m)
require.NoError(t, err) require.NoError(t, err)
// Required to skip configuration initialization that causes // Required to skip configuration initialization that causes
// DI errors in this test. // DI errors in this test.

@ -6,10 +6,12 @@ import (
"path/filepath" "path/filepath"
"sync" "sync"
"github.com/grafana/dskit/services"
"github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/modules"
plugifaces "github.com/grafana/grafana/pkg/plugins" 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/accesscontrol"
"github.com/grafana/grafana/pkg/services/alerting" "github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/services/correlations" "github.com/grafana/grafana/pkg/services/correlations"
@ -52,7 +54,7 @@ func ProvideService(
secrectService secrets.Service, secrectService secrets.Service,
orgService org.Service, orgService org.Service,
) (*ProvisioningServiceImpl, error) { ) (*ProvisioningServiceImpl, error) {
s := &ProvisioningServiceImpl{ ps := &ProvisioningServiceImpl{
Cfg: cfg, Cfg: cfg,
SQLStore: sqlStore, SQLStore: sqlStore,
ac: ac, ac: ac,
@ -76,12 +78,14 @@ func ProvideService(
log: log.New("provisioning"), log: log.New("provisioning"),
orgService: orgService, orgService: orgService,
} }
return s, nil
ps.BasicService = services.NewBasicService(ps.RunInitProvisioners, ps.Run, nil).WithName(modules.Provisioning)
return ps, nil
} }
type ProvisioningService interface { type ProvisioningService interface {
registry.BackgroundService services.NamedService
RunInitProvisioners(ctx context.Context) error
ProvisionDatasources(ctx context.Context) error ProvisionDatasources(ctx context.Context) error
ProvisionPlugins(ctx context.Context) error ProvisionPlugins(ctx context.Context) error
ProvisionNotifications(ctx context.Context) error ProvisionNotifications(ctx context.Context) error
@ -89,18 +93,21 @@ type ProvisioningService interface {
ProvisionAlerting(ctx context.Context) error ProvisionAlerting(ctx context.Context) error
GetDashboardProvisionerResolvedPath(name string) string GetDashboardProvisionerResolvedPath(name string) string
GetAllowUIUpdatesFromConfig(name string) bool GetAllowUIUpdatesFromConfig(name string) bool
RunInitProvisioners(ctx context.Context) error
} }
// Add a public constructor for overriding service to be able to instantiate OSS as fallback // Add a public constructor for overriding service to be able to instantiate OSS as fallback
func NewProvisioningServiceImpl() *ProvisioningServiceImpl { func NewProvisioningServiceImpl() *ProvisioningServiceImpl {
logger := log.New("provisioning") logger := log.New("provisioning")
return &ProvisioningServiceImpl{ ps := &ProvisioningServiceImpl{
log: logger, log: logger,
newDashboardProvisioner: dashboards.New, newDashboardProvisioner: dashboards.New,
provisionNotifiers: notifiers.Provision, provisionNotifiers: notifiers.Provision,
provisionDatasources: datasources.Provision, provisionDatasources: datasources.Provision,
provisionPlugins: plugins.Provision, provisionPlugins: plugins.Provision,
} }
ps.BasicService = services.NewBasicService(ps.RunInitProvisioners, ps.Run, nil).WithName(modules.Provisioning)
return ps
} }
// Used for testing purposes // Used for testing purposes
@ -110,16 +117,20 @@ func newProvisioningServiceImpl(
provisionDatasources func(context.Context, string, datasources.Store, datasources.CorrelationsStore, org.Service) 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, plugifaces.Store, pluginsettings.Service, org.Service) error,
) *ProvisioningServiceImpl { ) *ProvisioningServiceImpl {
return &ProvisioningServiceImpl{ ps := &ProvisioningServiceImpl{
log: log.New("provisioning"), log: log.New("provisioning"),
newDashboardProvisioner: newDashboardProvisioner, newDashboardProvisioner: newDashboardProvisioner,
provisionNotifiers: provisionNotifiers, provisionNotifiers: provisionNotifiers,
provisionDatasources: provisionDatasources, provisionDatasources: provisionDatasources,
provisionPlugins: provisionPlugins, provisionPlugins: provisionPlugins,
} }
ps.BasicService = services.NewBasicService(ps.RunInitProvisioners, ps.Run, nil).WithName(modules.Provisioning)
return ps
} }
type ProvisioningServiceImpl struct { type ProvisioningServiceImpl struct {
*services.BasicService
Cfg *setting.Cfg Cfg *setting.Cfg
SQLStore db.DB SQLStore db.DB
orgService org.Service orgService org.Service
@ -197,8 +208,10 @@ func (ps *ProvisioningServiceImpl) Run(ctx context.Context) error {
continue continue
case <-ctx.Done(): case <-ctx.Done():
// Root server context was cancelled so cancel polling and leave. // Root server context was cancelled so cancel polling and leave.
ps.mutex.Lock()
ps.cancelPolling() ps.cancelPolling()
return ctx.Err() ps.mutex.Unlock()
return nil
} }
} }
} }

@ -1,6 +1,12 @@
package provisioning package provisioning
import "context" import (
"context"
"github.com/grafana/dskit/services"
"github.com/grafana/grafana/pkg/modules"
)
type Calls struct { type Calls struct {
RunInitProvisioners []interface{} RunInitProvisioners []interface{}
@ -15,6 +21,7 @@ type Calls struct {
} }
type ProvisioningServiceMock struct { type ProvisioningServiceMock struct {
*services.BasicService
Calls *Calls Calls *Calls
RunInitProvisionersFunc func(ctx context.Context) error RunInitProvisionersFunc func(ctx context.Context) error
ProvisionDatasourcesFunc func(ctx context.Context) error ProvisionDatasourcesFunc func(ctx context.Context) error
@ -27,9 +34,11 @@ type ProvisioningServiceMock struct {
} }
func NewProvisioningServiceMock(ctx context.Context) *ProvisioningServiceMock { func NewProvisioningServiceMock(ctx context.Context) *ProvisioningServiceMock {
return &ProvisioningServiceMock{ s := &ProvisioningServiceMock{
Calls: &Calls{}, Calls: &Calls{},
} }
s.BasicService = services.NewBasicService(s.RunInitProvisioners, s.Run, nil).WithName(modules.Provisioning)
return s
} }
func (mock *ProvisioningServiceMock) RunInitProvisioners(ctx context.Context) error { func (mock *ProvisioningServiceMock) RunInitProvisioners(ctx context.Context) error {

@ -40,7 +40,7 @@ func TestProvisioningServiceImpl(t *testing.T) {
serviceTest.waitForStop() serviceTest.waitForStop()
assert.False(t, serviceTest.serviceRunning, "Service should not be running") assert.False(t, serviceTest.serviceRunning, "Service should not be running")
assert.Equal(t, context.Canceled, serviceTest.serviceError, "Service should have returned canceled error") assert.Nil(t, serviceTest.serviceError, "Service should not return canceled error")
}) })
t.Run("Failed reloading does not stop polling with old provisioned", func(t *testing.T) { t.Run("Failed reloading does not stop polling with old provisioned", func(t *testing.T) {

Loading…
Cancel
Save