mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
parent
18e66d22b1
commit
19a9a79467
@ -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(
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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{}
|
||||
|
@ -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
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user