Chore: Revert dskit service additions (#72608)
This commit is contained in:
@@ -1,28 +0,0 @@
|
||||
package modules
|
||||
|
||||
const (
|
||||
// All includes all modules necessary for Grafana to run as a standalone application.
|
||||
All string = "all"
|
||||
// BackgroundServices includes all Grafana services that run in the background
|
||||
BackgroundServices string = "background-services"
|
||||
// CertGenerator generates certificates for grafana-apiserver
|
||||
CertGenerator string = "cert-generator"
|
||||
// GrafanaAPIServer is the Kubertenes API server for Grafana Resources
|
||||
GrafanaAPIServer string = "grafana-apiserver"
|
||||
// HTTPServer is the HTTP server for Grafana
|
||||
HTTPServer string = "http-server"
|
||||
// Provisioning sets up Grafana with preconfigured datasources, dashboards, etc.
|
||||
Provisioning string = "provisioning"
|
||||
// SecretMigrator handles legacy secrets migrations
|
||||
SecretMigrator string = "secret-migrator"
|
||||
)
|
||||
|
||||
// dependencyMap defines Module Targets => Dependencies
|
||||
var dependencyMap = map[string][]string{
|
||||
BackgroundServices: {Provisioning, HTTPServer},
|
||||
CertGenerator: {},
|
||||
GrafanaAPIServer: {CertGenerator},
|
||||
Provisioning: {SecretMigrator},
|
||||
|
||||
All: {BackgroundServices},
|
||||
}
|
||||
+3
-11
@@ -21,19 +21,11 @@ func newServiceListener(logger log.Logger, s *service) *serviceListener {
|
||||
}
|
||||
|
||||
func (l *serviceListener) Healthy() {
|
||||
l.log.Info("All modules healthy", "modules", l.moduleNames())
|
||||
l.log.Info("All modules healthy")
|
||||
}
|
||||
|
||||
func (l *serviceListener) Stopped() {
|
||||
l.log.Info("All modules stopped", "modules", l.moduleNames())
|
||||
}
|
||||
|
||||
func (l *serviceListener) moduleNames() []string {
|
||||
var ms []string
|
||||
for m := range l.service.serviceMap {
|
||||
ms = append(ms, m)
|
||||
}
|
||||
return ms
|
||||
l.log.Info("All modules stopped")
|
||||
}
|
||||
|
||||
func (l *serviceListener) Failure(service services.Service) {
|
||||
@@ -43,7 +35,7 @@ func (l *serviceListener) Failure(service services.Service) {
|
||||
}
|
||||
|
||||
// log which module failed
|
||||
for module, s := range l.service.serviceMap {
|
||||
for module, s := range l.service.ServiceMap {
|
||||
if s == service {
|
||||
if errors.Is(service.FailureCase(), modules.ErrStopProcess) {
|
||||
l.log.Info("Received stop signal via return error", "module", module, "err", service.FailureCase())
|
||||
|
||||
+36
-87
@@ -3,7 +3,6 @@ package modules
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/dskit/modules"
|
||||
"github.com/grafana/dskit/services"
|
||||
@@ -11,19 +10,17 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/systemd"
|
||||
)
|
||||
|
||||
type Engine interface {
|
||||
AwaitHealthy(context.Context) error
|
||||
Init(context.Context) error
|
||||
Run(context.Context) error
|
||||
Shutdown(context.Context) error
|
||||
}
|
||||
|
||||
type Manager interface {
|
||||
RegisterModule(name string, initFn func() (services.Service, error))
|
||||
RegisterInvisibleModule(name string, initFn func() (services.Service, error))
|
||||
RegisterModule(name string, initFn func() (services.Service, error), deps ...string)
|
||||
RegisterInvisibleModule(name string, initFn func() (services.Service, error), deps ...string)
|
||||
}
|
||||
|
||||
var _ Engine = (*service)(nil)
|
||||
@@ -31,15 +28,14 @@ var _ Manager = (*service)(nil)
|
||||
|
||||
// service manages the registration and lifecycle of modules.
|
||||
type service struct {
|
||||
cfg *setting.Cfg
|
||||
log log.Logger
|
||||
targets []string
|
||||
cfg *setting.Cfg
|
||||
log log.Logger
|
||||
targets []string
|
||||
dependencyMap map[string][]string
|
||||
|
||||
moduleManager *modules.Manager
|
||||
serviceManager *services.Manager
|
||||
serviceMap map[string]services.Service
|
||||
|
||||
features *featuremgmt.FeatureManager
|
||||
ModuleManager *modules.Manager
|
||||
ServiceManager *services.Manager
|
||||
ServiceMap map[string]services.Service
|
||||
}
|
||||
|
||||
func ProvideService(
|
||||
@@ -49,55 +45,41 @@ func ProvideService(
|
||||
logger := log.New("modules")
|
||||
|
||||
return &service{
|
||||
cfg: cfg,
|
||||
log: logger,
|
||||
targets: cfg.Target,
|
||||
cfg: cfg,
|
||||
log: logger,
|
||||
targets: cfg.Target,
|
||||
dependencyMap: map[string][]string{},
|
||||
|
||||
moduleManager: modules.NewManager(logger),
|
||||
serviceMap: map[string]services.Service{},
|
||||
|
||||
features: features,
|
||||
ModuleManager: modules.NewManager(logger),
|
||||
ServiceMap: map[string]services.Service{},
|
||||
}
|
||||
}
|
||||
|
||||
// AwaitHealthy waits for all registered modules to be healthy.
|
||||
func (m *service) AwaitHealthy(ctx context.Context) error {
|
||||
if m.serviceManager == nil {
|
||||
return errors.New("service manager has not been initialized")
|
||||
}
|
||||
return m.serviceManager.AwaitHealthy(ctx)
|
||||
}
|
||||
|
||||
// Init initializes all registered modules.
|
||||
func (m *service) Init(_ context.Context) error {
|
||||
var err error
|
||||
|
||||
if err = m.processFeatureFlags(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.log.Debug("Initializing module manager", "targets", m.targets)
|
||||
for mod, targets := range dependencyMap {
|
||||
if err := m.moduleManager.AddDependency(mod, targets...); err != nil {
|
||||
for mod, targets := range m.dependencyMap {
|
||||
if err := m.ModuleManager.AddDependency(mod, targets...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
m.serviceMap, err = m.moduleManager.InitModuleServices(m.targets...)
|
||||
m.ServiceMap, err = m.ModuleManager.InitModuleServices(m.targets...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if no modules are registered, we don't need to start the service manager
|
||||
if len(m.serviceMap) == 0 {
|
||||
if len(m.ServiceMap) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var svcs []services.Service
|
||||
for _, s := range m.serviceMap {
|
||||
for _, s := range m.ServiceMap {
|
||||
svcs = append(svcs, s)
|
||||
}
|
||||
m.serviceManager, err = services.NewManager(svcs...)
|
||||
m.ServiceManager, err = services.NewManager(svcs...)
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -107,35 +89,28 @@ func (m *service) Run(ctx context.Context) error {
|
||||
// we don't need to continue if no modules are registered.
|
||||
// this behavior may need to change if dskit services replace the
|
||||
// current background service registry.
|
||||
if len(m.serviceMap) == 0 {
|
||||
if len(m.ServiceMap) == 0 {
|
||||
m.log.Warn("No modules registered...")
|
||||
<-ctx.Done()
|
||||
return nil
|
||||
}
|
||||
|
||||
listener := newServiceListener(m.log, m)
|
||||
m.serviceManager.AddListener(listener)
|
||||
m.ServiceManager.AddListener(listener)
|
||||
|
||||
m.log.Debug("Starting module service manager")
|
||||
// wait until a service fails or stop signal was received
|
||||
err := m.serviceManager.StartAsync(ctx)
|
||||
err := m.ServiceManager.StartAsync(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.serviceManager.AwaitHealthy(ctx)
|
||||
err = m.ServiceManager.AwaitStopped(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
systemd.NotifyReady(m.log)
|
||||
|
||||
err = m.serviceManager.AwaitStopped(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
failed := m.serviceManager.ServicesByState()[services.Failed]
|
||||
failed := m.ServiceManager.ServicesByState()[services.Failed]
|
||||
for _, f := range failed {
|
||||
// the service listener will log error details for all modules that failed,
|
||||
// so here we return the first error that is not ErrStopProcess
|
||||
@@ -149,55 +124,29 @@ func (m *service) Run(ctx context.Context) error {
|
||||
|
||||
// Shutdown stops all modules and waits for them to stop.
|
||||
func (m *service) Shutdown(ctx context.Context) error {
|
||||
if m.serviceManager == nil {
|
||||
if m.ServiceManager == nil {
|
||||
m.log.Debug("No modules registered, nothing to stop...")
|
||||
return nil
|
||||
}
|
||||
m.serviceManager.StopAsync()
|
||||
m.ServiceManager.StopAsync()
|
||||
m.log.Info("Awaiting services to be stopped...")
|
||||
return m.serviceManager.AwaitStopped(ctx)
|
||||
return m.ServiceManager.AwaitStopped(ctx)
|
||||
}
|
||||
|
||||
// RegisterModule registers a module with the dskit module manager.
|
||||
func (m *service) RegisterModule(name string, initFn func() (services.Service, error)) {
|
||||
m.moduleManager.RegisterModule(name, initFn)
|
||||
func (m *service) RegisterModule(name string, initFn func() (services.Service, error), deps ...string) {
|
||||
m.ModuleManager.RegisterModule(name, initFn)
|
||||
m.dependencyMap[name] = deps
|
||||
}
|
||||
|
||||
// RegisterInvisibleModule registers an invisible module with the dskit module manager.
|
||||
// Invisible modules are not visible to the user, and are intended to be used as dependencies.
|
||||
func (m *service) RegisterInvisibleModule(name string, initFn func() (services.Service, error)) {
|
||||
m.moduleManager.RegisterModule(name, initFn, modules.UserInvisibleModule)
|
||||
// Invisible modules are not visible to the user, and are intendent to be used as dependencies.
|
||||
func (m *service) RegisterInvisibleModule(name string, initFn func() (services.Service, error), deps ...string) {
|
||||
m.ModuleManager.RegisterModule(name, initFn, modules.UserInvisibleModule)
|
||||
m.dependencyMap[name] = deps
|
||||
}
|
||||
|
||||
// IsModuleEnabled returns true if the module is enabled.
|
||||
func (m *service) IsModuleEnabled(name string) bool {
|
||||
return stringsContain(m.targets, name)
|
||||
}
|
||||
|
||||
// processFeatureFlags adds or removes targets based on feature flags.
|
||||
func (m *service) processFeatureFlags() error {
|
||||
// add GrafanaAPIServer to targets if feature is enabled
|
||||
if m.features.IsEnabled(featuremgmt.FlagGrafanaAPIServer) {
|
||||
m.targets = append(m.targets, GrafanaAPIServer)
|
||||
}
|
||||
|
||||
if !m.features.IsEnabled(featuremgmt.FlagGrafanaAPIServer) {
|
||||
// error if GrafanaAPIServer is in targets
|
||||
for _, t := range m.targets {
|
||||
if t == GrafanaAPIServer {
|
||||
return fmt.Errorf("feature flag %s is disabled, but target %s is still enabled", featuremgmt.FlagGrafanaAPIServer, GrafanaAPIServer)
|
||||
}
|
||||
}
|
||||
|
||||
// error if GrafanaAPIServer is a dependency of a target
|
||||
for parent, targets := range dependencyMap {
|
||||
for _, t := range targets {
|
||||
if t == GrafanaAPIServer && m.IsModuleEnabled(parent) {
|
||||
return fmt.Errorf("feature flag %s is disabled, but target %s is enabled with dependency on %s", featuremgmt.FlagGrafanaAPIServer, parent, GrafanaAPIServer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"github.com/grafana/dskit/services"
|
||||
"github.com/grafana/grafana-apiserver/pkg/certgenerator"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/modules"
|
||||
"github.com/grafana/grafana/pkg/registry/backgroundsvcs"
|
||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/provisioning"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/kvstore/migrations"
|
||||
)
|
||||
|
||||
type Registry interface{}
|
||||
|
||||
type registry struct {
|
||||
moduleManager modules.Manager
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func ProvideRegistry(
|
||||
moduleManager modules.Manager,
|
||||
apiServer grafanaapiserver.Service,
|
||||
backgroundServiceRunner *backgroundsvcs.BackgroundServiceRunner,
|
||||
certGenerator certgenerator.ServiceInterface,
|
||||
httpServer *api.HTTPServer,
|
||||
provisioningService *provisioning.ProvisioningServiceImpl,
|
||||
secretsMigrator *migrations.SecretMigrationProviderImpl,
|
||||
) *registry {
|
||||
return newRegistry(
|
||||
log.New("modules.registry"),
|
||||
moduleManager,
|
||||
apiServer,
|
||||
backgroundServiceRunner,
|
||||
certGenerator,
|
||||
httpServer,
|
||||
provisioningService,
|
||||
secretsMigrator,
|
||||
)
|
||||
}
|
||||
|
||||
func newRegistry(logger log.Logger, moduleManager modules.Manager, svcs ...services.NamedService) *registry {
|
||||
r := ®istry{
|
||||
log: logger,
|
||||
moduleManager: moduleManager,
|
||||
}
|
||||
|
||||
// Register (invisible) modules which act solely as dependencies to module targets
|
||||
for _, svc := range svcs {
|
||||
s := svc
|
||||
logger.Debug("Registering invisible module", "name", s.ServiceName())
|
||||
r.moduleManager.RegisterInvisibleModule(s.ServiceName(), func() (services.Service, error) {
|
||||
return s, nil
|
||||
})
|
||||
}
|
||||
|
||||
logger.Debug("Registering module", "name", modules.All)
|
||||
r.moduleManager.RegisterModule(modules.All, nil)
|
||||
|
||||
return r
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/dskit/services"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/modules"
|
||||
)
|
||||
|
||||
func TestNewRegistry(t *testing.T) {
|
||||
var registeredInvisibleModules []string
|
||||
var registeredModules []string
|
||||
|
||||
moduleManager := &modules.MockModuleManager{
|
||||
RegisterModuleFunc: func(name string, initFn func() (services.Service, error)) {
|
||||
registeredModules = append(registeredModules, name)
|
||||
},
|
||||
RegisterInvisibleModuleFunc: func(name string, initFn func() (services.Service, error)) {
|
||||
registeredInvisibleModules = append(registeredInvisibleModules, name)
|
||||
},
|
||||
}
|
||||
|
||||
mockSvcName := "test-registry"
|
||||
mockSvc := modules.NewMockNamedService(mockSvcName)
|
||||
|
||||
r := newRegistry(log.New("modules.registry"), moduleManager, mockSvc)
|
||||
require.NotNil(t, r)
|
||||
require.Equal(t, []string{mockSvcName}, registeredInvisibleModules)
|
||||
require.Equal(t, []string{modules.All}, registeredModules)
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package registry
|
||||
|
||||
import "github.com/google/wire"
|
||||
|
||||
var WireSet = wire.NewSet(
|
||||
ProvideRegistry,
|
||||
wire.Bind(new(Registry), new(*registry)),
|
||||
)
|
||||
@@ -1,66 +1,5 @@
|
||||
package modules
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/dskit/services"
|
||||
)
|
||||
|
||||
var _ Manager = (*MockModuleManager)(nil)
|
||||
var _ Engine = (*MockModuleEngine)(nil)
|
||||
|
||||
type MockModuleManager struct {
|
||||
RegisterModuleFunc func(name string, initFn func() (services.Service, error))
|
||||
RegisterInvisibleModuleFunc func(name string, initFn func() (services.Service, error))
|
||||
}
|
||||
|
||||
func (m *MockModuleManager) RegisterModule(name string, initFn func() (services.Service, error)) {
|
||||
if m.RegisterModuleFunc != nil {
|
||||
m.RegisterModuleFunc(name, initFn)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MockModuleManager) RegisterInvisibleModule(name string, initFn func() (services.Service, error)) {
|
||||
if m.RegisterInvisibleModuleFunc != nil {
|
||||
m.RegisterInvisibleModuleFunc(name, initFn)
|
||||
}
|
||||
}
|
||||
|
||||
type MockModuleEngine struct {
|
||||
AwaitHealthyFunc func(context.Context) error
|
||||
InitFunc func(context.Context) error
|
||||
RunFunc func(context.Context) error
|
||||
ShutdownFunc func(context.Context) error
|
||||
}
|
||||
|
||||
func (m *MockModuleEngine) AwaitHealthy(ctx context.Context) error {
|
||||
if m.AwaitHealthyFunc != nil {
|
||||
return m.AwaitHealthyFunc(ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockModuleEngine) Init(ctx context.Context) error {
|
||||
if m.InitFunc != nil {
|
||||
return m.InitFunc(ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockModuleEngine) Run(ctx context.Context) error {
|
||||
if m.RunFunc != nil {
|
||||
return m.RunFunc(ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockModuleEngine) Shutdown(ctx context.Context) error {
|
||||
if m.ShutdownFunc != nil {
|
||||
return m.ShutdownFunc(ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func stringsContain(values []string, search string) bool {
|
||||
for _, v := range values {
|
||||
if search == v {
|
||||
@@ -70,14 +9,3 @@ func stringsContain(values []string, search string) bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type MockNamedService struct {
|
||||
*services.BasicService
|
||||
}
|
||||
|
||||
func NewMockNamedService(name string) *MockNamedService {
|
||||
startFn := func(_ context.Context) error { return nil }
|
||||
return &MockNamedService{
|
||||
BasicService: services.NewIdleService(startFn, nil).WithName(name),
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -1,8 +1,6 @@
|
||||
package modules
|
||||
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
)
|
||||
import "github.com/google/wire"
|
||||
|
||||
var WireSet = wire.NewSet(
|
||||
ProvideService,
|
||||
|
||||
Reference in New Issue
Block a user