Alerting: Publish event when one or more rules are created or changed (#93637)

* Publish event when one or more rules are changed

* Publish affected rules

* Use a fake bus to test publish event without listening

* Wire alerting store into provisioning service
This commit is contained in:
William Wernert 2024-10-11 12:19:52 -04:00 committed by GitHub
parent 18e66d22b1
commit 19a9a79467
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 238 additions and 114 deletions

View File

@ -782,7 +782,7 @@ func setUpServiceTest(t *testing.T, withDashboardMock bool) cloudmigration.Servi
fakeAccessControlService := actest.FakeService{}
alertMetrics := metrics.NewNGAlert(prometheus.NewRegistry())
ruleStore, err := ngalertstore.ProvideDBStore(cfg, featureToggles, sqlStore, mockFolder, dashboardService, fakeAccessControl)
ruleStore, err := ngalertstore.ProvideDBStore(cfg, featureToggles, sqlStore, mockFolder, dashboardService, fakeAccessControl, bus)
require.NoError(t, err)
ng, err := ngalert.ProvideService(

View File

@ -494,7 +494,7 @@ func TestIntegrationNestedFolderService(t *testing.T) {
dashSrv, err := dashboardservice.ProvideDashboardServiceImpl(cfg, dashStore, folderStore, featuresFlagOn, folderPermissions, dashboardPermissions, ac, serviceWithFlagOn, nestedFolderStore, nil)
require.NoError(t, err)
alertStore, err := ngstore.ProvideDBStore(cfg, featuresFlagOn, db, serviceWithFlagOn, dashSrv, ac)
alertStore, err := ngstore.ProvideDBStore(cfg, featuresFlagOn, db, serviceWithFlagOn, dashSrv, ac, b)
require.NoError(t, err)
elementService := libraryelements.ProvideService(cfg, db, routeRegister, serviceWithFlagOn, serviceWithFlagOn.store, featuresFlagOn, ac)
@ -577,7 +577,7 @@ func TestIntegrationNestedFolderService(t *testing.T) {
folderPermissions, dashboardPermissions, ac, serviceWithFlagOff, nestedFolderStore, nil)
require.NoError(t, err)
alertStore, err := ngstore.ProvideDBStore(cfg, featuresFlagOff, db, serviceWithFlagOff, dashSrv, ac)
alertStore, err := ngstore.ProvideDBStore(cfg, featuresFlagOff, db, serviceWithFlagOff, dashSrv, ac, b)
require.NoError(t, err)
elementService := libraryelements.ProvideService(cfg, db, routeRegister, serviceWithFlagOff, serviceWithFlagOff.store, featuresFlagOff, ac)
@ -722,7 +722,7 @@ func TestIntegrationNestedFolderService(t *testing.T) {
dashSrv, err := dashboardservice.ProvideDashboardServiceImpl(cfg, dashStore, folderStore, tc.featuresFlag, folderPermissions, dashboardPermissions, ac, tc.service, tc.service.store, nil)
require.NoError(t, err)
alertStore, err := ngstore.ProvideDBStore(cfg, tc.featuresFlag, db, tc.service, dashSrv, ac)
alertStore, err := ngstore.ProvideDBStore(cfg, tc.featuresFlag, db, tc.service, dashSrv, ac, b)
require.NoError(t, err)
ancestors := CreateSubtreeInStore(t, nestedFolderStore, serviceWithFlagOn, tc.depth, tc.prefix, createCmd, true)

View File

@ -1830,6 +1830,7 @@ func createTestEnv(t *testing.T, testConfig string) testEnvironment {
BaseInterval: time.Second * 10,
},
FolderService: folderService,
Bus: bus.ProvideBus(tracing.InitializeTracerForTest()),
}
user := &user.SignedInUser{
OrgID: 1,

View File

@ -1647,6 +1647,7 @@ func createAlertRuleService(t *testing.T, folderService folder.Service) AlertRul
},
Logger: log.NewNopLogger(),
FolderService: folderService,
Bus: bus.ProvideBus(tracing.InitializeTracerForTest()),
}
// store := fakes.NewRuleStore(t)
quotas := MockQuotaChecker{}

View File

@ -46,6 +46,15 @@ func (st DBstore) DeleteAlertRulesByUID(ctx context.Context, orgID int64, ruleUI
return err
}
logger.Debug("Deleted alert rules", "count", rows)
if rows > 0 {
keys := make([]ngmodels.AlertRuleKey, 0, len(ruleUID))
for _, uid := range ruleUID {
keys = append(keys, ngmodels.AlertRuleKey{OrgID: orgID, UID: uid})
}
_ = st.Bus.Publish(ctx, &RuleChangeEvent{
RuleKeys: keys,
})
}
rows, err = sess.Table(alertRuleVersion{}).Where("rule_org_id = ?", orgID).In("rule_uid", ruleUID).Delete(alertRule{})
if err != nil {
@ -173,6 +182,7 @@ func (st DBstore) GetAlertRulesGroupByRuleUID(ctx context.Context, query *ngmode
// Returns the UID and ID of rules that were created in the same order as the input rules.
func (st DBstore) InsertAlertRules(ctx context.Context, rules []ngmodels.AlertRule) ([]ngmodels.AlertRuleKeyWithId, error) {
ids := make([]ngmodels.AlertRuleKeyWithId, 0, len(rules))
keys := make([]ngmodels.AlertRuleKey, 0, len(rules))
return ids, st.SQLStore.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
newRules := make([]alertRule, 0, len(rules))
ruleVersions := make([]alertRuleVersion, 0, len(rules))
@ -211,13 +221,10 @@ func (st DBstore) InsertAlertRules(ctx context.Context, rules []ngmodels.AlertRu
return fmt.Errorf("failed to create new rules: %w", err)
}
r := newRules[i]
ids = append(ids, ngmodels.AlertRuleKeyWithId{
AlertRuleKey: ngmodels.AlertRuleKey{
OrgID: r.OrgID,
UID: r.UID,
},
ID: r.ID,
})
key := ngmodels.AlertRuleKey{OrgID: r.OrgID, UID: r.UID}
ids = append(ids, ngmodels.AlertRuleKeyWithId{AlertRuleKey: key, ID: r.ID})
keys = append(keys, key)
}
}
@ -226,6 +233,12 @@ func (st DBstore) InsertAlertRules(ctx context.Context, rules []ngmodels.AlertRu
return fmt.Errorf("failed to create new rule versions: %w", err)
}
}
if len(keys) > 0 {
_ = st.Bus.Publish(ctx, &RuleChangeEvent{
RuleKeys: keys,
})
}
return nil
})
}
@ -239,6 +252,7 @@ func (st DBstore) UpdateAlertRules(ctx context.Context, rules []ngmodels.UpdateR
}
ruleVersions := make([]alertRuleVersion, 0, len(rules))
keys := make([]ngmodels.AlertRuleKey, 0, len(rules))
for i := range rules {
// We do indexed access way to avoid "G601: Implicit memory aliasing in for loop."
// Doing this will be unnecessary with go 1.22 https://stackoverflow.com/a/68247837/767660
@ -269,6 +283,7 @@ func (st DBstore) UpdateAlertRules(ctx context.Context, rules []ngmodels.UpdateR
v.Version++
v.ParentVersion = r.Existing.Version
ruleVersions = append(ruleVersions, v)
keys = append(keys, ngmodels.AlertRuleKey{OrgID: r.New.OrgID, UID: r.New.UID})
}
if len(ruleVersions) > 0 {
if _, err := sess.Insert(&ruleVersions); err != nil {
@ -283,7 +298,11 @@ func (st DBstore) UpdateAlertRules(ctx context.Context, rules []ngmodels.UpdateR
}
}
}
if len(keys) > 0 {
_ = st.Bus.Publish(ctx, &RuleChangeEvent{
RuleKeys: keys,
})
}
return nil
})
}

View File

@ -43,12 +43,11 @@ func TestIntegrationUpdateAlertRules(t *testing.T) {
cfg := setting.NewCfg()
cfg.UnifiedAlerting = setting.UnifiedAlertingSettings{BaseInterval: time.Duration(rand.Int63n(100)+1) * time.Second}
sqlStore := db.InitTestDB(t)
store := &DBstore{
SQLStore: sqlStore,
Cfg: cfg.UnifiedAlerting,
FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()),
Logger: &logtest.Fake{},
}
logger := &logtest.Fake{}
folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())
b := &fakeBus{}
store := createTestStore(sqlStore, folderService, logger, cfg.UnifiedAlerting, b)
gen := models.RuleGen
gen = gen.With(gen.WithIntervalMatching(store.Cfg.BaseInterval))
recordingRuleGen := gen.With(gen.WithAllRecordingRules())
@ -113,6 +112,29 @@ func TestIntegrationUpdateAlertRules(t *testing.T) {
require.ErrorIs(t, err, ErrOptimisticLock)
})
t.Run("should emit event when rules are updated", func(t *testing.T) {
rule := createRule(t, store, gen)
called := false
b.publishFn = func(ctx context.Context, msg bus.Msg) error {
event, ok := msg.(*RuleChangeEvent)
require.True(t, ok)
require.NotNil(t, event)
require.Len(t, event.RuleKeys, 1)
require.Equal(t, rule.GetKey(), event.RuleKeys[0])
called = true
return nil
}
newRule := models.CopyRule(rule)
newRule.Title = util.GenerateShortUID()
err := store.UpdateAlertRules(context.Background(), []models.UpdateRule{{
Existing: rule,
New: *newRule,
}})
require.NoError(t, err)
require.True(t, called)
})
}
func TestIntegrationUpdateAlertRulesWithUniqueConstraintViolation(t *testing.T) {
@ -122,12 +144,9 @@ func TestIntegrationUpdateAlertRulesWithUniqueConstraintViolation(t *testing.T)
cfg := setting.NewCfg()
cfg.UnifiedAlerting = setting.UnifiedAlertingSettings{BaseInterval: time.Duration(rand.Int63n(100)+1) * time.Second}
sqlStore := db.InitTestDB(t)
store := &DBstore{
SQLStore: sqlStore,
Cfg: cfg.UnifiedAlerting,
FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()),
Logger: &logtest.Fake{},
}
folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())
b := &fakeBus{}
store := createTestStore(sqlStore, folderService, &logtest.Fake{}, cfg.UnifiedAlerting, b)
gen := models.RuleGen
createRuleInFolder := func(title string, orgID int64, namespaceUID string) *models.AlertRule {
@ -379,13 +398,11 @@ func TestIntegration_GetAlertRulesForScheduling(t *testing.T) {
}
sqlStore := db.InitTestDB(t)
store := &DBstore{
Logger: &logtest.Fake{},
SQLStore: sqlStore,
Cfg: cfg.UnifiedAlerting,
FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()),
FeatureToggles: featuremgmt.WithFeatures(),
}
folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())
b := &fakeBus{}
logger := &logtest.Fake{}
store := createTestStore(sqlStore, folderService, logger, cfg.UnifiedAlerting, b)
store.FeatureToggles = featuremgmt.WithFeatures()
gen := models.RuleGen
gen = gen.With(gen.WithIntervalMatching(store.Cfg.BaseInterval), gen.WithUniqueOrgID())
@ -504,7 +521,9 @@ func TestIntegration_CountAlertRules(t *testing.T) {
sqlStore := db.InitTestDB(t)
cfg := setting.NewCfg()
store := &DBstore{SQLStore: sqlStore, FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())}
folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())
b := &fakeBus{}
store := createTestStore(sqlStore, folderService, &logtest.Fake{}, cfg.UnifiedAlerting, b)
gen := models.RuleGen
gen = gen.With(gen.WithIntervalMatching(store.Cfg.BaseInterval), gen.WithRandomRecordingRules())
@ -569,11 +588,11 @@ func TestIntegration_DeleteInFolder(t *testing.T) {
sqlStore := db.InitTestDB(t)
cfg := setting.NewCfg()
store := &DBstore{
SQLStore: sqlStore,
FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()),
Logger: log.New("test-dbstore"),
}
folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())
b := &fakeBus{}
logger := log.New("test-dbstore")
store := createTestStore(sqlStore, folderService, logger, cfg.UnifiedAlerting, b)
rule := createRule(t, store, nil)
t.Run("should not be able to delete folder without permissions to delete rules", func(t *testing.T) {
@ -595,6 +614,38 @@ func TestIntegration_DeleteInFolder(t *testing.T) {
})
}
func TestIntegration_DeleteAlertRulesByUID(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
sqlStore := db.InitTestDB(t)
cfg := setting.NewCfg()
folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())
b := &fakeBus{}
logger := log.New("test-dbstore")
store := createTestStore(sqlStore, folderService, logger, cfg.UnifiedAlerting, b)
gen := models.RuleGen
t.Run("should emit event when rules are deleted", func(t *testing.T) {
rule := createRule(t, store, gen)
called := false
b.publishFn = func(ctx context.Context, msg bus.Msg) error {
event, ok := msg.(*RuleChangeEvent)
require.True(t, ok)
require.NotNil(t, event)
require.Len(t, event.RuleKeys, 1)
require.Equal(t, rule.GetKey(), event.RuleKeys[0])
called = true
return nil
}
err := store.DeleteAlertRulesByUID(context.Background(), rule.OrgID, rule.UID)
require.NoError(t, err)
require.True(t, called)
})
}
func TestIntegration_GetNamespaceByUID(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
@ -602,11 +653,10 @@ func TestIntegration_GetNamespaceByUID(t *testing.T) {
sqlStore := db.InitTestDB(t)
cfg := setting.NewCfg()
store := &DBstore{
SQLStore: sqlStore,
FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()),
Logger: log.New("test-dbstore"),
}
folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())
b := &fakeBus{}
logger := log.New("test-dbstore")
store := createTestStore(sqlStore, folderService, logger, cfg.UnifiedAlerting, b)
u := &user.SignedInUser{
UserID: 1,
@ -657,12 +707,10 @@ func TestIntegrationInsertAlertRules(t *testing.T) {
sqlStore := db.InitTestDB(t)
cfg := setting.NewCfg()
cfg.UnifiedAlerting.BaseInterval = 1 * time.Second
store := &DBstore{
SQLStore: sqlStore,
FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()),
Logger: log.New("test-dbstore"),
Cfg: cfg.UnifiedAlerting,
}
folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())
b := &fakeBus{}
logger := log.New("test-dbstore")
store := createTestStore(sqlStore, folderService, logger, cfg.UnifiedAlerting, b)
gen := models.RuleGen.With(
models.RuleGen.WithOrgID(orgID),
@ -790,6 +838,25 @@ func TestIntegrationInsertAlertRules(t *testing.T) {
require.ErrorIs(t, err, models.ErrAlertRuleConflictBase)
require.ErrorContains(t, err, "rule UID under the same organisation should be unique")
})
t.Run("should emit event when rules are inserted", func(t *testing.T) {
rule := gen.Generate()
called := false
b.publishFn = func(ctx context.Context, msg bus.Msg) error {
event, ok := msg.(*RuleChangeEvent)
require.True(t, ok)
require.NotNil(t, event)
require.Len(t, event.RuleKeys, 1)
require.Equal(t, rule.GetKey(), event.RuleKeys[0])
called = true
return nil
}
rules, err := store.InsertAlertRules(context.Background(), []models.AlertRule{rule})
require.NoError(t, err)
require.Len(t, rules, 1)
require.True(t, called)
})
}
func TestIntegrationAlertRulesNotificationSettings(t *testing.T) {
@ -808,12 +875,10 @@ func TestIntegrationAlertRulesNotificationSettings(t *testing.T) {
sqlStore := db.InitTestDB(t)
cfg := setting.NewCfg()
cfg.UnifiedAlerting.BaseInterval = 1 * time.Second
store := &DBstore{
SQLStore: sqlStore,
FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()),
Logger: log.New("test-dbstore"),
Cfg: cfg.UnifiedAlerting,
}
folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())
b := &fakeBus{}
logger := log.New("test-dbstore")
store := createTestStore(sqlStore, folderService, logger, cfg.UnifiedAlerting, b)
receiverName := "receiver\"-" + uuid.NewString()
timeIntervalName := "time-" + util.GenerateShortUID()
@ -1082,14 +1147,12 @@ func TestIntegrationListNotificationSettings(t *testing.T) {
}
sqlStore := db.InitTestDB(t)
folderService := setupFolderService(t, sqlStore, setting.NewCfg(), featuremgmt.WithFeatures())
logger := log.New("test-dbstore")
cfg := setting.NewCfg()
cfg.UnifiedAlerting.BaseInterval = 1 * time.Second
store := &DBstore{
SQLStore: sqlStore,
FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()),
Logger: log.New("test-dbstore"),
Cfg: cfg.UnifiedAlerting,
}
b := &fakeBus{}
store := createTestStore(sqlStore, folderService, logger, cfg.UnifiedAlerting, b)
searchName := `name-%"-👍'test`
gen := models.RuleGen
@ -1207,12 +1270,10 @@ func TestIntegrationGetNamespacesByRuleUID(t *testing.T) {
sqlStore := db.InitTestDB(t)
cfg := setting.NewCfg()
cfg.UnifiedAlerting.BaseInterval = 1 * time.Second
store := &DBstore{
SQLStore: sqlStore,
FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()),
Logger: log.New("test-dbstore"),
Cfg: cfg.UnifiedAlerting,
}
folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())
b := &fakeBus{}
logger := log.New("test-dbstore")
store := createTestStore(sqlStore, folderService, logger, cfg.UnifiedAlerting, b)
rules := models.RuleGen.With(models.RuleMuts.WithOrgID(1), models.RuleMuts.WithRandomRecordingRules()).GenerateMany(5)
_, err := store.InsertAlertRules(context.Background(), rules)
@ -1258,13 +1319,11 @@ func TestIntegrationRuleGroupsCaseSensitive(t *testing.T) {
sqlStore := db.InitTestDB(t)
cfg := setting.NewCfg()
cfg.UnifiedAlerting.BaseInterval = 1 * time.Second
store := &DBstore{
SQLStore: sqlStore,
FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()),
Logger: log.New("test-dbstore"),
Cfg: cfg.UnifiedAlerting,
FeatureToggles: featuremgmt.WithFeatures(),
}
folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())
b := &fakeBus{}
logger := log.New("test-dbstore")
store := createTestStore(sqlStore, folderService, logger, cfg.UnifiedAlerting, b)
store.FeatureToggles = featuremgmt.WithFeatures()
gen := models.RuleGen.With(models.RuleMuts.WithOrgID(1))
misc := gen.GenerateMany(5, 10)
@ -1365,12 +1424,9 @@ func TestIncreaseVersionForAllRulesInNamespaces(t *testing.T) {
cfg := setting.NewCfg()
cfg.UnifiedAlerting = setting.UnifiedAlertingSettings{BaseInterval: time.Duration(rand.Int63n(100)+1) * time.Second}
sqlStore := db.InitTestDB(t)
store := &DBstore{
SQLStore: sqlStore,
Cfg: cfg.UnifiedAlerting,
FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()),
Logger: &logtest.Fake{},
}
folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())
b := &fakeBus{}
store := createTestStore(sqlStore, folderService, &logtest.Fake{}, cfg.UnifiedAlerting, b)
orgID := int64(1)
gen := models.RuleGen
gen = gen.With(gen.WithIntervalMatching(store.Cfg.BaseInterval)).With(gen.WithOrgID(orgID))
@ -1482,12 +1538,9 @@ func TestIntegration_AlertRuleVersionsCleanup(t *testing.T) {
BaseInterval: time.Duration(rand.Int63n(100)+1) * time.Second,
}
sqlStore := db.InitTestDB(t)
store := &DBstore{
SQLStore: sqlStore,
Cfg: cfg.UnifiedAlerting,
FolderService: setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()),
Logger: &logtest.Fake{},
}
folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures())
b := &fakeBus{}
store := createTestStore(sqlStore, folderService, &logtest.Fake{}, cfg.UnifiedAlerting, b)
generator := models.RuleGen
generator = generator.With(generator.WithIntervalMatching(store.Cfg.BaseInterval), generator.WithUniqueOrgID())
@ -1601,3 +1654,33 @@ func TestIntegration_AlertRuleVersionsCleanup(t *testing.T) {
require.Error(t, err)
})
}
func createTestStore(
sqlStore db.DB,
folderService folder.Service,
logger log.Logger,
cfg setting.UnifiedAlertingSettings,
bus bus.Bus,
) *DBstore {
return &DBstore{
SQLStore: sqlStore,
FolderService: folderService,
Logger: logger,
Cfg: cfg,
Bus: bus,
}
}
type fakeBus struct {
publishFn func(ctx context.Context, msg bus.Msg) error
}
func (f *fakeBus) AddEventListener(handler bus.HandlerFunc) {}
func (f *fakeBus) Publish(ctx context.Context, msg bus.Msg) error {
if f.publishFn != nil {
return f.publishFn(ctx, msg)
}
return nil
}

View File

@ -4,6 +4,7 @@ import (
"context"
"time"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/accesscontrol"
@ -41,10 +42,18 @@ type DBstore struct {
FolderService folder.Service
DashboardService dashboards.DashboardService
AccessControl accesscontrol.AccessControl
Bus bus.Bus
}
func ProvideDBStore(
cfg *setting.Cfg, featureToggles featuremgmt.FeatureToggles, sqlstore db.DB, folderService folder.Service, dashboards dashboards.DashboardService, ac accesscontrol.AccessControl) (*DBstore, error) {
cfg *setting.Cfg,
featureToggles featuremgmt.FeatureToggles,
sqlstore db.DB,
folderService folder.Service,
dashboards dashboards.DashboardService,
ac accesscontrol.AccessControl,
bus bus.Bus,
) (*DBstore, error) {
store := DBstore{
Cfg: cfg.UnifiedAlerting,
FeatureToggles: featureToggles,
@ -53,9 +62,14 @@ func ProvideDBStore(
FolderService: folderService,
DashboardService: dashboards,
AccessControl: ac,
Bus: bus,
}
if err := folderService.RegisterService(store); err != nil {
return nil, err
}
return &store, nil
}
type RuleChangeEvent struct {
RuleKeys []models.AlertRuleKey
}

View File

@ -7,8 +7,10 @@ import (
"testing"
"time"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/log/logtest"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/folder/foldertest"
"github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/setting"
@ -146,6 +148,7 @@ func SetupStoreForTesting(t *testing.T, db db.DB) *DBstore {
Cfg: cfg.UnifiedAlerting,
FolderService: service,
Logger: &logtest.Fake{},
Bus: bus.ProvideBus(tracing.InitializeTracerForTest()),
}
return store
}

View File

@ -65,7 +65,7 @@ func SetupTestEnv(tb testing.TB, baseInterval time.Duration) (*ngalert.AlertNG,
dashboardService, dashboardStore := testutil.SetupDashboardService(tb, sqlStore, folderStore, cfg)
features := featuremgmt.WithFeatures()
folderService := testutil.SetupFolderService(tb, cfg, sqlStore, dashboardStore, folderStore, bus, features, ac)
ruleStore, err := store.ProvideDBStore(cfg, featuremgmt.WithFeatures(), sqlStore, folderService, &dashboards.FakeDashboardService{}, ac)
ruleStore, err := store.ProvideDBStore(cfg, featuremgmt.WithFeatures(), sqlStore, folderService, &dashboards.FakeDashboardService{}, ac, bus)
require.NoError(tb, err)
ng, err := ngalert.ProvideService(
cfg, features, nil, nil, routing.NewRouteRegister(), sqlStore, kvstore.NewFakeKVStore(), nil, nil, quotatest.New(false, nil),
@ -82,6 +82,7 @@ func SetupTestEnv(tb testing.TB, baseInterval time.Duration) (*ngalert.AlertNG,
Logger: log.New("ngalert-test"),
DashboardService: dashboardService,
FolderService: folderService,
Bus: bus,
}
}

View File

@ -22,7 +22,7 @@ import (
"github.com/grafana/grafana/pkg/services/ngalert/notifier"
"github.com/grafana/grafana/pkg/services/ngalert/notifier/legacy_storage"
"github.com/grafana/grafana/pkg/services/ngalert/provisioning"
"github.com/grafana/grafana/pkg/services/ngalert/store"
alertstore "github.com/grafana/grafana/pkg/services/ngalert/store"
"github.com/grafana/grafana/pkg/services/notifications"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
@ -42,6 +42,7 @@ func ProvideService(
cfg *setting.Cfg,
sqlStore db.DB,
pluginStore pluginstore.Store,
alertingStore *alertstore.DBstore,
encryptionService encryption.Internal,
notificatonService *notifications.NotificationService,
dashboardProvisioningService dashboardservice.DashboardProvisioningService,
@ -62,6 +63,7 @@ func ProvideService(
SQLStore: sqlStore,
ac: ac,
pluginStore: pluginStore,
alertingStore: alertingStore,
EncryptionService: encryptionService,
NotificationService: notificatonService,
newDashboardProvisioner: dashboards.New,
@ -139,6 +141,7 @@ type ProvisioningServiceImpl struct {
orgService org.Service
ac accesscontrol.AccessControl
pluginStore pluginstore.Store
alertingStore *alertstore.DBstore
EncryptionService encryption.Internal
NotificationService *notifications.NotificationService
log log.Logger
@ -263,16 +266,9 @@ func (ps *ProvisioningServiceImpl) ProvisionDashboards(ctx context.Context) erro
func (ps *ProvisioningServiceImpl) ProvisionAlerting(ctx context.Context) error {
alertingPath := filepath.Join(ps.Cfg.ProvisioningPath, "alerting")
st := store.DBstore{
Cfg: ps.Cfg.UnifiedAlerting,
SQLStore: ps.SQLStore,
Logger: ps.log,
FolderService: nil, // we don't use it yet
DashboardService: ps.dashboardService,
}
ruleService := provisioning.NewAlertRuleService(
st,
st,
ps.alertingStore,
ps.alertingStore,
ps.folderService,
//ps.dashboardService,
ps.quotaService,
@ -281,15 +277,15 @@ func (ps *ProvisioningServiceImpl) ProvisionAlerting(ctx context.Context) error
int64(ps.Cfg.UnifiedAlerting.BaseInterval.Seconds()),
ps.Cfg.UnifiedAlerting.RulesPerRuleGroupLimit,
ps.log,
notifier.NewCachedNotificationSettingsValidationService(&st),
notifier.NewCachedNotificationSettingsValidationService(ps.alertingStore),
alertingauthz.NewRuleService(ps.ac),
)
configStore := legacy_storage.NewAlertmanagerConfigStore(&st)
configStore := legacy_storage.NewAlertmanagerConfigStore(ps.alertingStore)
receiverSvc := notifier.NewReceiverService(
alertingauthz.NewReceiverAccess[*ngmodels.Receiver](ps.ac, true),
configStore,
st,
st,
ps.alertingStore,
ps.alertingStore,
ps.secretService,
ps.SQLStore,
ps.log,
@ -297,11 +293,11 @@ func (ps *ProvisioningServiceImpl) ProvisionAlerting(ctx context.Context) error
ps.tracer,
)
contactPointService := provisioning.NewContactPointService(configStore, ps.secretService,
st, ps.SQLStore, receiverSvc, ps.log, &st, ps.resourcePermissions)
ps.alertingStore, ps.SQLStore, receiverSvc, ps.log, ps.alertingStore, ps.resourcePermissions)
notificationPolicyService := provisioning.NewNotificationPolicyService(configStore,
st, ps.SQLStore, ps.Cfg.UnifiedAlerting, ps.log)
mutetimingsService := provisioning.NewMuteTimingService(configStore, st, &st, ps.log, &st)
templateService := provisioning.NewTemplateService(configStore, st, &st, ps.log)
ps.alertingStore, ps.SQLStore, ps.Cfg.UnifiedAlerting, ps.log)
mutetimingsService := provisioning.NewMuteTimingService(configStore, ps.alertingStore, ps.alertingStore, ps.log, ps.alertingStore)
templateService := provisioning.NewTemplateService(configStore, ps.alertingStore, ps.alertingStore, ps.log)
cfg := prov_alerting.ProvisionerConfig{
Path: alertingPath,
RuleService: *ruleService,

View File

@ -496,7 +496,7 @@ func setupEnv(t *testing.T, sqlStore db.DB, cfg *setting.Cfg, b bus.Bus, quotaSe
m := metrics.NewNGAlert(prometheus.NewRegistry())
ac := acimpl.ProvideAccessControl(featuremgmt.WithFeatures(), zanzana.NewNoopClient())
ruleStore, err := ngstore.ProvideDBStore(cfg, featuremgmt.WithFeatures(), sqlStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac)
ruleStore, err := ngstore.ProvideDBStore(cfg, featuremgmt.WithFeatures(), sqlStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac, b)
require.NoError(t, err)
_, err = ngalert.ProvideService(
cfg, featuremgmt.WithFeatures(), nil, nil, routing.NewRouteRegister(), sqlStore, ngalertfakes.NewFakeKVStore(t), nil, nil, quotaService,

View File

@ -23,8 +23,10 @@ import (
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
"github.com/grafana/grafana/pkg/apis/alerting_notifications/v0alpha1"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/generated/clientset/versioned"
notificationsv0alpha1 "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/alerting_notifications/v0alpha1"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol"
@ -870,7 +872,7 @@ func TestIntegrationProvisioning(t *testing.T) {
env := helper.GetEnv()
ac := acimpl.ProvideAccessControl(env.FeatureToggles, zanzana.NewNoopClient())
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac)
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac, bus.ProvideBus(tracing.InitializeTracerForTest()))
require.NoError(t, err)
created, err := adminClient.Create(ctx, &v0alpha1.Receiver{
@ -1127,7 +1129,7 @@ func TestIntegrationReferentialIntegrity(t *testing.T) {
helper := getTestHelper(t)
env := helper.GetEnv()
ac := acimpl.ProvideAccessControl(env.FeatureToggles, zanzana.NewNoopClient())
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac)
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac, bus.ProvideBus(tracing.InitializeTracerForTest()))
require.NoError(t, err)
orgID := helper.Org1.Admin.Identity.GetOrgID()
@ -1447,7 +1449,7 @@ func TestIntegrationReceiverListSelector(t *testing.T) {
env := helper.GetEnv()
ac := acimpl.ProvideAccessControl(env.FeatureToggles, zanzana.NewNoopClient())
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac)
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac, bus.ProvideBus(tracing.InitializeTracerForTest()))
require.NoError(t, err)
require.NoError(t, db.SetProvenance(ctx, &definitions.EmbeddedContactPoint{
UID: *recv2.Spec.Integrations[0].Uid,

View File

@ -13,7 +13,9 @@ import (
"k8s.io/apimachinery/pkg/types"
"github.com/grafana/grafana/pkg/apis/alerting_notifications/v0alpha1"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/generated/clientset/versioned"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
@ -355,7 +357,7 @@ func TestIntegrationProvisioning(t *testing.T) {
env := helper.GetEnv()
ac := acimpl.ProvideAccessControl(env.FeatureToggles, zanzana.NewNoopClient())
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac)
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac, bus.ProvideBus(tracing.InitializeTracerForTest()))
require.NoError(t, err)
created, err := adminClient.Create(ctx, &v0alpha1.TemplateGroup{
@ -579,7 +581,7 @@ func TestIntegrationListSelector(t *testing.T) {
require.NoError(t, err)
env := helper.GetEnv()
ac := acimpl.ProvideAccessControl(env.FeatureToggles, zanzana.NewNoopClient())
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac)
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac, bus.ProvideBus(tracing.InitializeTracerForTest()))
require.NoError(t, err)
require.NoError(t, db.SetProvenance(ctx, &definitions.NotificationTemplate{
Name: template2.Spec.Title,

View File

@ -18,7 +18,9 @@ import (
"k8s.io/apimachinery/pkg/types"
"github.com/grafana/grafana/pkg/apis/alerting_notifications/v0alpha1"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/generated/clientset/versioned"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
@ -365,7 +367,7 @@ func TestIntegrationTimeIntervalProvisioning(t *testing.T) {
env := helper.GetEnv()
ac := acimpl.ProvideAccessControl(env.FeatureToggles, zanzana.NewNoopClient())
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac)
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac, bus.ProvideBus(tracing.InitializeTracerForTest()))
require.NoError(t, err)
created, err := adminClient.Create(ctx, &v0alpha1.TimeInterval{
@ -593,7 +595,7 @@ func TestIntegrationTimeIntervalListSelector(t *testing.T) {
require.NoError(t, err)
env := helper.GetEnv()
ac := acimpl.ProvideAccessControl(env.FeatureToggles, zanzana.NewNoopClient())
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac)
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac, bus.ProvideBus(tracing.InitializeTracerForTest()))
require.NoError(t, err)
require.NoError(t, db.SetProvenance(ctx, &definitions.MuteTimeInterval{
MuteTimeInterval: config.MuteTimeInterval{
@ -653,7 +655,7 @@ func TestIntegrationTimeIntervalReferentialIntegrity(t *testing.T) {
helper := getTestHelper(t)
env := helper.GetEnv()
ac := acimpl.ProvideAccessControl(env.FeatureToggles, zanzana.NewNoopClient())
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac)
db, err := store.ProvideDBStore(env.Cfg, env.FeatureToggles, env.SQLStore, &foldertest.FakeService{}, &dashboards.FakeDashboardService{}, ac, bus.ProvideBus(tracing.InitializeTracerForTest()))
require.NoError(t, err)
orgID := helper.Org1.Admin.Identity.GetOrgID()