mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Move fake rule store to the test utilities package (#56062)
* Move fakeRuleStore to tests/fakes package * Break stub dependencies on store * Update existing tests to point to new location * Remove unused stub of TimeNow * Rename fake to take advantage of package name
This commit is contained in:
parent
82d7f80a15
commit
c16317e5b8
@ -20,7 +20,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/ngalert/eval"
|
"github.com/grafana/grafana/pkg/services/ngalert/eval"
|
||||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/state"
|
"github.com/grafana/grafana/pkg/services/ngalert/state"
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
"github.com/grafana/grafana/pkg/services/ngalert/tests/fakes"
|
||||||
"github.com/grafana/grafana/pkg/services/org"
|
"github.com/grafana/grafana/pkg/services/org"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
@ -423,7 +423,7 @@ func TestRouteGetRuleStatuses(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("with many rules in a group", func(t *testing.T) {
|
t.Run("with many rules in a group", func(t *testing.T) {
|
||||||
t.Run("should return sorted", func(t *testing.T) {
|
t.Run("should return sorted", func(t *testing.T) {
|
||||||
ruleStore := store.NewFakeRuleStore(t)
|
ruleStore := fakes.NewRuleStore(t)
|
||||||
fakeAIM := NewFakeAlertInstanceManager(t)
|
fakeAIM := NewFakeAlertInstanceManager(t)
|
||||||
groupKey := ngmodels.GenerateGroupKey(orgID)
|
groupKey := ngmodels.GenerateGroupKey(orgID)
|
||||||
_, rules := ngmodels.GenerateUniqueAlertRules(rand.Intn(5)+5, ngmodels.AlertRuleGen(withGroupKey(groupKey), ngmodels.WithUniqueGroupIndex()))
|
_, rules := ngmodels.GenerateUniqueAlertRules(rand.Intn(5)+5, ngmodels.AlertRuleGen(withGroupKey(groupKey), ngmodels.WithUniqueGroupIndex()))
|
||||||
@ -466,7 +466,7 @@ func TestRouteGetRuleStatuses(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("when fine-grained access is enabled", func(t *testing.T) {
|
t.Run("when fine-grained access is enabled", func(t *testing.T) {
|
||||||
t.Run("should return only rules if the user can query all data sources", func(t *testing.T) {
|
t.Run("should return only rules if the user can query all data sources", func(t *testing.T) {
|
||||||
ruleStore := store.NewFakeRuleStore(t)
|
ruleStore := fakes.NewRuleStore(t)
|
||||||
fakeAIM := NewFakeAlertInstanceManager(t)
|
fakeAIM := NewFakeAlertInstanceManager(t)
|
||||||
|
|
||||||
rules := ngmodels.GenerateAlertRules(rand.Intn(4)+2, ngmodels.AlertRuleGen(withOrgID(orgID)))
|
rules := ngmodels.GenerateAlertRules(rand.Intn(4)+2, ngmodels.AlertRuleGen(withOrgID(orgID)))
|
||||||
@ -503,8 +503,8 @@ func TestRouteGetRuleStatuses(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupAPI(t *testing.T) (*store.FakeRuleStore, *fakeAlertInstanceManager, *acmock.Mock, PrometheusSrv) {
|
func setupAPI(t *testing.T) (*fakes.RuleStore, *fakeAlertInstanceManager, *acmock.Mock, PrometheusSrv) {
|
||||||
fakeStore := store.NewFakeRuleStore(t)
|
fakeStore := fakes.NewRuleStore(t)
|
||||||
fakeAIM := NewFakeAlertInstanceManager(t)
|
fakeAIM := NewFakeAlertInstanceManager(t)
|
||||||
acMock := acmock.New().WithDisabled()
|
acMock := acmock.New().WithDisabled()
|
||||||
|
|
||||||
@ -518,7 +518,7 @@ func setupAPI(t *testing.T) (*store.FakeRuleStore, *fakeAlertInstanceManager, *a
|
|||||||
return fakeStore, fakeAIM, acMock, api
|
return fakeStore, fakeAIM, acMock, api
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateRuleAndInstanceWithQuery(t *testing.T, orgID int64, fakeAIM *fakeAlertInstanceManager, fakeStore *store.FakeRuleStore, query func(r *ngmodels.AlertRule)) {
|
func generateRuleAndInstanceWithQuery(t *testing.T, orgID int64, fakeAIM *fakeAlertInstanceManager, fakeStore *fakes.RuleStore, query func(r *ngmodels.AlertRule)) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
rules := ngmodels.GenerateAlertRules(1, ngmodels.AlertRuleGen(withOrgID(orgID), asFixture(), query))
|
rules := ngmodels.GenerateAlertRules(1, ngmodels.AlertRuleGen(withOrgID(orgID), asFixture(), query))
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/ngalert/provisioning"
|
"github.com/grafana/grafana/pkg/services/ngalert/provisioning"
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/schedule"
|
"github.com/grafana/grafana/pkg/services/ngalert/schedule"
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||||
|
"github.com/grafana/grafana/pkg/services/ngalert/tests/fakes"
|
||||||
"github.com/grafana/grafana/pkg/services/org"
|
"github.com/grafana/grafana/pkg/services/org"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
@ -30,22 +31,22 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestRouteDeleteAlertRules(t *testing.T) {
|
func TestRouteDeleteAlertRules(t *testing.T) {
|
||||||
getRecordedCommand := func(ruleStore *store.FakeRuleStore) []store.GenericRecordedQuery {
|
getRecordedCommand := func(ruleStore *fakes.RuleStore) []fakes.GenericRecordedQuery {
|
||||||
results := ruleStore.GetRecordedCommands(func(cmd interface{}) (interface{}, bool) {
|
results := ruleStore.GetRecordedCommands(func(cmd interface{}) (interface{}, bool) {
|
||||||
c, ok := cmd.(store.GenericRecordedQuery)
|
c, ok := cmd.(fakes.GenericRecordedQuery)
|
||||||
if !ok || c.Name != "DeleteAlertRulesByUID" {
|
if !ok || c.Name != "DeleteAlertRulesByUID" {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
return c, ok
|
return c, ok
|
||||||
})
|
})
|
||||||
var result []store.GenericRecordedQuery
|
var result []fakes.GenericRecordedQuery
|
||||||
for _, cmd := range results {
|
for _, cmd := range results {
|
||||||
result = append(result, cmd.(store.GenericRecordedQuery))
|
result = append(result, cmd.(fakes.GenericRecordedQuery))
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
assertRulesDeleted := func(t *testing.T, expectedRules []*models.AlertRule, ruleStore *store.FakeRuleStore, scheduler *schedule.FakeScheduleService) {
|
assertRulesDeleted := func(t *testing.T, expectedRules []*models.AlertRule, ruleStore *fakes.RuleStore, scheduler *schedule.FakeScheduleService) {
|
||||||
deleteCommands := getRecordedCommand(ruleStore)
|
deleteCommands := getRecordedCommand(ruleStore)
|
||||||
require.Len(t, deleteCommands, 1)
|
require.Len(t, deleteCommands, 1)
|
||||||
cmd := deleteCommands[0]
|
cmd := deleteCommands[0]
|
||||||
@ -73,8 +74,8 @@ func TestRouteDeleteAlertRules(t *testing.T) {
|
|||||||
orgID := rand.Int63()
|
orgID := rand.Int63()
|
||||||
folder := randFolder()
|
folder := randFolder()
|
||||||
|
|
||||||
initFakeRuleStore := func(t *testing.T) *store.FakeRuleStore {
|
initFakeRuleStore := func(t *testing.T) *fakes.RuleStore {
|
||||||
ruleStore := store.NewFakeRuleStore(t)
|
ruleStore := fakes.NewRuleStore(t)
|
||||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||||
// add random data
|
// add random data
|
||||||
ruleStore.PutRule(context.Background(), models.GenerateAlertRulesSmallNonEmpty(models.AlertRuleGen(withOrgID(orgID)))...)
|
ruleStore.PutRule(context.Background(), models.GenerateAlertRulesSmallNonEmpty(models.AlertRuleGen(withOrgID(orgID)))...)
|
||||||
@ -267,7 +268,7 @@ func TestRouteGetNamespaceRulesConfig(t *testing.T) {
|
|||||||
t.Run("should return rules for which user has access to data source", func(t *testing.T) {
|
t.Run("should return rules for which user has access to data source", func(t *testing.T) {
|
||||||
orgID := rand.Int63()
|
orgID := rand.Int63()
|
||||||
folder := randFolder()
|
folder := randFolder()
|
||||||
ruleStore := store.NewFakeRuleStore(t)
|
ruleStore := fakes.NewRuleStore(t)
|
||||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||||
expectedRules := models.GenerateAlertRules(rand.Intn(4)+2, models.AlertRuleGen(withOrgID(orgID), withNamespace(folder)))
|
expectedRules := models.GenerateAlertRules(rand.Intn(4)+2, models.AlertRuleGen(withOrgID(orgID), withNamespace(folder)))
|
||||||
ruleStore.PutRule(context.Background(), expectedRules...)
|
ruleStore.PutRule(context.Background(), expectedRules...)
|
||||||
@ -303,7 +304,7 @@ func TestRouteGetNamespaceRulesConfig(t *testing.T) {
|
|||||||
t.Run("should return all rules from folder", func(t *testing.T) {
|
t.Run("should return all rules from folder", func(t *testing.T) {
|
||||||
orgID := rand.Int63()
|
orgID := rand.Int63()
|
||||||
folder := randFolder()
|
folder := randFolder()
|
||||||
ruleStore := store.NewFakeRuleStore(t)
|
ruleStore := fakes.NewRuleStore(t)
|
||||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||||
expectedRules := models.GenerateAlertRules(rand.Intn(4)+2, models.AlertRuleGen(withOrgID(orgID), withNamespace(folder)))
|
expectedRules := models.GenerateAlertRules(rand.Intn(4)+2, models.AlertRuleGen(withOrgID(orgID), withNamespace(folder)))
|
||||||
ruleStore.PutRule(context.Background(), expectedRules...)
|
ruleStore.PutRule(context.Background(), expectedRules...)
|
||||||
@ -337,7 +338,7 @@ func TestRouteGetNamespaceRulesConfig(t *testing.T) {
|
|||||||
t.Run("should return the provenance of the alert rules", func(t *testing.T) {
|
t.Run("should return the provenance of the alert rules", func(t *testing.T) {
|
||||||
orgID := rand.Int63()
|
orgID := rand.Int63()
|
||||||
folder := randFolder()
|
folder := randFolder()
|
||||||
ruleStore := store.NewFakeRuleStore(t)
|
ruleStore := fakes.NewRuleStore(t)
|
||||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||||
expectedRules := models.GenerateAlertRules(rand.Intn(4)+2, models.AlertRuleGen(withOrgID(orgID), withNamespace(folder)))
|
expectedRules := models.GenerateAlertRules(rand.Intn(4)+2, models.AlertRuleGen(withOrgID(orgID), withNamespace(folder)))
|
||||||
ruleStore.PutRule(context.Background(), expectedRules...)
|
ruleStore.PutRule(context.Background(), expectedRules...)
|
||||||
@ -378,7 +379,7 @@ func TestRouteGetNamespaceRulesConfig(t *testing.T) {
|
|||||||
t.Run("should enforce order of rules in the group", func(t *testing.T) {
|
t.Run("should enforce order of rules in the group", func(t *testing.T) {
|
||||||
orgID := rand.Int63()
|
orgID := rand.Int63()
|
||||||
folder := randFolder()
|
folder := randFolder()
|
||||||
ruleStore := store.NewFakeRuleStore(t)
|
ruleStore := fakes.NewRuleStore(t)
|
||||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||||
groupKey := models.GenerateGroupKey(orgID)
|
groupKey := models.GenerateGroupKey(orgID)
|
||||||
groupKey.NamespaceUID = folder.Uid
|
groupKey.NamespaceUID = folder.Uid
|
||||||
@ -422,7 +423,7 @@ func TestRouteGetRulesConfig(t *testing.T) {
|
|||||||
t.Run("fine-grained access is enabled", func(t *testing.T) {
|
t.Run("fine-grained access is enabled", func(t *testing.T) {
|
||||||
t.Run("should check access to data source", func(t *testing.T) {
|
t.Run("should check access to data source", func(t *testing.T) {
|
||||||
orgID := rand.Int63()
|
orgID := rand.Int63()
|
||||||
ruleStore := store.NewFakeRuleStore(t)
|
ruleStore := fakes.NewRuleStore(t)
|
||||||
folder1 := randFolder()
|
folder1 := randFolder()
|
||||||
folder2 := randFolder()
|
folder2 := randFolder()
|
||||||
ruleStore.Folders[orgID] = []*models2.Folder{folder1, folder2}
|
ruleStore.Folders[orgID] = []*models2.Folder{folder1, folder2}
|
||||||
@ -460,7 +461,7 @@ func TestRouteGetRulesConfig(t *testing.T) {
|
|||||||
t.Run("should return rules in group sorted by group index", func(t *testing.T) {
|
t.Run("should return rules in group sorted by group index", func(t *testing.T) {
|
||||||
orgID := rand.Int63()
|
orgID := rand.Int63()
|
||||||
folder := randFolder()
|
folder := randFolder()
|
||||||
ruleStore := store.NewFakeRuleStore(t)
|
ruleStore := fakes.NewRuleStore(t)
|
||||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||||
groupKey := models.GenerateGroupKey(orgID)
|
groupKey := models.GenerateGroupKey(orgID)
|
||||||
groupKey.NamespaceUID = folder.Uid
|
groupKey.NamespaceUID = folder.Uid
|
||||||
@ -505,7 +506,7 @@ func TestRouteGetRulesGroupConfig(t *testing.T) {
|
|||||||
t.Run("should check access to data source", func(t *testing.T) {
|
t.Run("should check access to data source", func(t *testing.T) {
|
||||||
orgID := rand.Int63()
|
orgID := rand.Int63()
|
||||||
folder := randFolder()
|
folder := randFolder()
|
||||||
ruleStore := store.NewFakeRuleStore(t)
|
ruleStore := fakes.NewRuleStore(t)
|
||||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||||
groupKey := models.GenerateGroupKey(orgID)
|
groupKey := models.GenerateGroupKey(orgID)
|
||||||
groupKey.NamespaceUID = folder.Uid
|
groupKey.NamespaceUID = folder.Uid
|
||||||
@ -540,7 +541,7 @@ func TestRouteGetRulesGroupConfig(t *testing.T) {
|
|||||||
t.Run("should return rules in group sorted by group index", func(t *testing.T) {
|
t.Run("should return rules in group sorted by group index", func(t *testing.T) {
|
||||||
orgID := rand.Int63()
|
orgID := rand.Int63()
|
||||||
folder := randFolder()
|
folder := randFolder()
|
||||||
ruleStore := store.NewFakeRuleStore(t)
|
ruleStore := fakes.NewRuleStore(t)
|
||||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||||
groupKey := models.GenerateGroupKey(orgID)
|
groupKey := models.GenerateGroupKey(orgID)
|
||||||
groupKey.NamespaceUID = folder.Uid
|
groupKey.NamespaceUID = folder.Uid
|
||||||
@ -636,13 +637,13 @@ func TestVerifyProvisionedRulesNotAffected(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func createServiceWithProvenanceStore(ac *acMock.Mock, store *store.FakeRuleStore, scheduler schedule.ScheduleService, provenanceStore provisioning.ProvisioningStore) *RulerSrv {
|
func createServiceWithProvenanceStore(ac *acMock.Mock, store *fakes.RuleStore, scheduler schedule.ScheduleService, provenanceStore provisioning.ProvisioningStore) *RulerSrv {
|
||||||
svc := createService(ac, store, scheduler)
|
svc := createService(ac, store, scheduler)
|
||||||
svc.provenanceStore = provenanceStore
|
svc.provenanceStore = provenanceStore
|
||||||
return svc
|
return svc
|
||||||
}
|
}
|
||||||
|
|
||||||
func createService(ac *acMock.Mock, store *store.FakeRuleStore, scheduler schedule.ScheduleService) *RulerSrv {
|
func createService(ac *acMock.Mock, store *fakes.RuleStore, scheduler schedule.ScheduleService) *RulerSrv {
|
||||||
return &RulerSrv{
|
return &RulerSrv{
|
||||||
xactManager: store,
|
xactManager: store,
|
||||||
store: store,
|
store: store,
|
||||||
|
@ -15,7 +15,7 @@ import (
|
|||||||
models2 "github.com/grafana/grafana/pkg/models"
|
models2 "github.com/grafana/grafana/pkg/models"
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/schedule"
|
"github.com/grafana/grafana/pkg/services/ngalert/schedule"
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
"github.com/grafana/grafana/pkg/services/ngalert/tests/fakes"
|
||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ func Test_subscribeToFolderChanges(t *testing.T) {
|
|||||||
rules := models.GenerateAlertRules(5, models.AlertRuleGen(models.WithOrgID(orgID), models.WithNamespace(folder)))
|
rules := models.GenerateAlertRules(5, models.AlertRuleGen(models.WithOrgID(orgID), models.WithNamespace(folder)))
|
||||||
|
|
||||||
bus := busmock.New()
|
bus := busmock.New()
|
||||||
db := store.NewFakeRuleStore(t)
|
db := fakes.NewRuleStore(t)
|
||||||
db.Folders[orgID] = append(db.Folders[orgID], folder)
|
db.Folders[orgID] = append(db.Folders[orgID], folder)
|
||||||
db.PutRule(context.Background(), rules...)
|
db.PutRule(context.Background(), rules...)
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ func Test_subscribeToFolderChanges(t *testing.T) {
|
|||||||
|
|
||||||
require.Eventuallyf(t, func() bool {
|
require.Eventuallyf(t, func() bool {
|
||||||
return len(db.GetRecordedCommands(func(cmd interface{}) (interface{}, bool) {
|
return len(db.GetRecordedCommands(func(cmd interface{}) (interface{}, bool) {
|
||||||
c, ok := cmd.(store.GenericRecordedQuery)
|
c, ok := cmd.(fakes.GenericRecordedQuery)
|
||||||
if !ok || c.Name != "IncreaseVersionForAllRulesInNamespace" {
|
if !ok || c.Name != "IncreaseVersionForAllRulesInNamespace" {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
grafana_models "github.com/grafana/grafana/pkg/models"
|
grafana_models "github.com/grafana/grafana/pkg/models"
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||||
|
"github.com/grafana/grafana/pkg/services/ngalert/tests/fakes"
|
||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -19,7 +20,7 @@ func TestCalculateChanges(t *testing.T) {
|
|||||||
orgId := rand.Int63()
|
orgId := rand.Int63()
|
||||||
|
|
||||||
t.Run("detects alerts that need to be added", func(t *testing.T) {
|
t.Run("detects alerts that need to be added", func(t *testing.T) {
|
||||||
fakeStore := NewFakeRuleStore(t)
|
fakeStore := fakes.NewRuleStore(t)
|
||||||
|
|
||||||
groupKey := models.GenerateGroupKey(orgId)
|
groupKey := models.GenerateGroupKey(orgId)
|
||||||
submitted := models.GenerateAlertRules(rand.Intn(5)+1, models.AlertRuleGen(withOrgID(orgId), simulateSubmitted, withoutUID))
|
submitted := models.GenerateAlertRules(rand.Intn(5)+1, models.AlertRuleGen(withOrgID(orgId), simulateSubmitted, withoutUID))
|
||||||
@ -46,7 +47,7 @@ func TestCalculateChanges(t *testing.T) {
|
|||||||
groupKey := models.GenerateGroupKey(orgId)
|
groupKey := models.GenerateGroupKey(orgId)
|
||||||
inDatabaseMap, inDatabase := models.GenerateUniqueAlertRules(rand.Intn(5)+1, models.AlertRuleGen(withGroupKey(groupKey)))
|
inDatabaseMap, inDatabase := models.GenerateUniqueAlertRules(rand.Intn(5)+1, models.AlertRuleGen(withGroupKey(groupKey)))
|
||||||
|
|
||||||
fakeStore := NewFakeRuleStore(t)
|
fakeStore := fakes.NewRuleStore(t)
|
||||||
fakeStore.PutRule(context.Background(), inDatabase...)
|
fakeStore.PutRule(context.Background(), inDatabase...)
|
||||||
|
|
||||||
changes, err := CalculateChanges(context.Background(), fakeStore, groupKey, make([]*models.AlertRule, 0))
|
changes, err := CalculateChanges(context.Background(), fakeStore, groupKey, make([]*models.AlertRule, 0))
|
||||||
@ -70,7 +71,7 @@ func TestCalculateChanges(t *testing.T) {
|
|||||||
inDatabaseMap, inDatabase := models.GenerateUniqueAlertRules(rand.Intn(5)+1, models.AlertRuleGen(withGroupKey(groupKey)))
|
inDatabaseMap, inDatabase := models.GenerateUniqueAlertRules(rand.Intn(5)+1, models.AlertRuleGen(withGroupKey(groupKey)))
|
||||||
submittedMap, submitted := models.GenerateUniqueAlertRules(len(inDatabase), models.AlertRuleGen(simulateSubmitted, withGroupKey(groupKey), withUIDs(inDatabaseMap)))
|
submittedMap, submitted := models.GenerateUniqueAlertRules(len(inDatabase), models.AlertRuleGen(simulateSubmitted, withGroupKey(groupKey), withUIDs(inDatabaseMap)))
|
||||||
|
|
||||||
fakeStore := NewFakeRuleStore(t)
|
fakeStore := fakes.NewRuleStore(t)
|
||||||
fakeStore.PutRule(context.Background(), inDatabase...)
|
fakeStore.PutRule(context.Background(), inDatabase...)
|
||||||
|
|
||||||
changes, err := CalculateChanges(context.Background(), fakeStore, groupKey, submitted)
|
changes, err := CalculateChanges(context.Background(), fakeStore, groupKey, submitted)
|
||||||
@ -108,7 +109,7 @@ func TestCalculateChanges(t *testing.T) {
|
|||||||
submitted = append(submitted, r)
|
submitted = append(submitted, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeStore := NewFakeRuleStore(t)
|
fakeStore := fakes.NewRuleStore(t)
|
||||||
fakeStore.PutRule(context.Background(), inDatabase...)
|
fakeStore.PutRule(context.Background(), inDatabase...)
|
||||||
|
|
||||||
changes, err := CalculateChanges(context.Background(), fakeStore, groupKey, submitted)
|
changes, err := CalculateChanges(context.Background(), fakeStore, groupKey, submitted)
|
||||||
@ -159,7 +160,7 @@ func TestCalculateChanges(t *testing.T) {
|
|||||||
|
|
||||||
dbRule := models.AlertRuleGen(withOrgID(orgId))()
|
dbRule := models.AlertRuleGen(withOrgID(orgId))()
|
||||||
|
|
||||||
fakeStore := NewFakeRuleStore(t)
|
fakeStore := fakes.NewRuleStore(t)
|
||||||
fakeStore.PutRule(context.Background(), dbRule)
|
fakeStore.PutRule(context.Background(), dbRule)
|
||||||
|
|
||||||
groupKey := models.GenerateGroupKey(orgId)
|
groupKey := models.GenerateGroupKey(orgId)
|
||||||
@ -185,7 +186,7 @@ func TestCalculateChanges(t *testing.T) {
|
|||||||
sourceGroupKey := models.GenerateGroupKey(orgId)
|
sourceGroupKey := models.GenerateGroupKey(orgId)
|
||||||
inDatabaseMap, inDatabase := models.GenerateUniqueAlertRules(rand.Intn(10)+10, models.AlertRuleGen(withGroupKey(sourceGroupKey)))
|
inDatabaseMap, inDatabase := models.GenerateUniqueAlertRules(rand.Intn(10)+10, models.AlertRuleGen(withGroupKey(sourceGroupKey)))
|
||||||
|
|
||||||
fakeStore := NewFakeRuleStore(t)
|
fakeStore := fakes.NewRuleStore(t)
|
||||||
fakeStore.PutRule(context.Background(), inDatabase...)
|
fakeStore.PutRule(context.Background(), inDatabase...)
|
||||||
|
|
||||||
namespace := randFolder()
|
namespace := randFolder()
|
||||||
@ -221,7 +222,7 @@ func TestCalculateChanges(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("should fail when submitted rule has UID that does not exist in db", func(t *testing.T) {
|
t.Run("should fail when submitted rule has UID that does not exist in db", func(t *testing.T) {
|
||||||
fakeStore := NewFakeRuleStore(t)
|
fakeStore := fakes.NewRuleStore(t)
|
||||||
groupKey := models.GenerateGroupKey(orgId)
|
groupKey := models.GenerateGroupKey(orgId)
|
||||||
submitted := models.AlertRuleGen(withOrgID(orgId), simulateSubmitted)()
|
submitted := models.AlertRuleGen(withOrgID(orgId), simulateSubmitted)()
|
||||||
require.NotEqual(t, "", submitted.UID)
|
require.NotEqual(t, "", submitted.UID)
|
||||||
@ -231,7 +232,7 @@ func TestCalculateChanges(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("should fail if cannot fetch current rules in the group", func(t *testing.T) {
|
t.Run("should fail if cannot fetch current rules in the group", func(t *testing.T) {
|
||||||
fakeStore := NewFakeRuleStore(t)
|
fakeStore := fakes.NewRuleStore(t)
|
||||||
expectedErr := errors.New("TEST ERROR")
|
expectedErr := errors.New("TEST ERROR")
|
||||||
fakeStore.Hook = func(cmd interface{}) error {
|
fakeStore.Hook = func(cmd interface{}) error {
|
||||||
switch cmd.(type) {
|
switch cmd.(type) {
|
||||||
@ -249,7 +250,7 @@ func TestCalculateChanges(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("should fail if cannot fetch rule by UID", func(t *testing.T) {
|
t.Run("should fail if cannot fetch rule by UID", func(t *testing.T) {
|
||||||
fakeStore := NewFakeRuleStore(t)
|
fakeStore := fakes.NewRuleStore(t)
|
||||||
expectedErr := errors.New("TEST ERROR")
|
expectedErr := errors.New("TEST ERROR")
|
||||||
fakeStore.Hook = func(cmd interface{}) error {
|
fakeStore.Hook = func(cmd interface{}) error {
|
||||||
switch cmd.(type) {
|
switch cmd.(type) {
|
||||||
|
@ -2,16 +2,10 @@ package store
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
|
||||||
"github.com/grafana/grafana/pkg/util"
|
|
||||||
|
|
||||||
models2 "github.com/grafana/grafana/pkg/models"
|
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -66,331 +60,6 @@ func (s *FakeImageStore) SaveImage(_ context.Context, image *models.Image) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFakeRuleStore(t *testing.T) *FakeRuleStore {
|
|
||||||
return &FakeRuleStore{
|
|
||||||
t: t,
|
|
||||||
Rules: map[int64][]*models.AlertRule{},
|
|
||||||
Hook: func(interface{}) error {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
Folders: map[int64][]*models2.Folder{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FakeRuleStore mocks the RuleStore of the scheduler.
|
|
||||||
type FakeRuleStore struct {
|
|
||||||
t *testing.T
|
|
||||||
mtx sync.Mutex
|
|
||||||
// OrgID -> RuleGroup -> Namespace -> Rules
|
|
||||||
Rules map[int64][]*models.AlertRule
|
|
||||||
Hook func(cmd interface{}) error // use Hook if you need to intercept some query and return an error
|
|
||||||
RecordedOps []interface{}
|
|
||||||
Folders map[int64][]*models2.Folder
|
|
||||||
}
|
|
||||||
|
|
||||||
type GenericRecordedQuery struct {
|
|
||||||
Name string
|
|
||||||
Params []interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PutRule puts the rule in the Rules map. If there are existing rule in the same namespace, they will be overwritten
|
|
||||||
func (f *FakeRuleStore) PutRule(_ context.Context, rules ...*models.AlertRule) {
|
|
||||||
f.mtx.Lock()
|
|
||||||
defer f.mtx.Unlock()
|
|
||||||
mainloop:
|
|
||||||
for _, r := range rules {
|
|
||||||
rgs := f.Rules[r.OrgID]
|
|
||||||
for idx, rulePtr := range rgs {
|
|
||||||
if rulePtr.UID == r.UID {
|
|
||||||
rgs[idx] = r
|
|
||||||
continue mainloop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rgs = append(rgs, r)
|
|
||||||
f.Rules[r.OrgID] = rgs
|
|
||||||
|
|
||||||
var existing *models2.Folder
|
|
||||||
folders := f.Folders[r.OrgID]
|
|
||||||
for _, folder := range folders {
|
|
||||||
if folder.Uid == r.NamespaceUID {
|
|
||||||
existing = folder
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if existing == nil {
|
|
||||||
folders = append(folders, &models2.Folder{
|
|
||||||
Id: rand.Int63(),
|
|
||||||
Uid: r.NamespaceUID,
|
|
||||||
Title: "TEST-FOLDER-" + util.GenerateShortUID(),
|
|
||||||
})
|
|
||||||
f.Folders[r.OrgID] = folders
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRecordedCommands filters recorded commands using predicate function. Returns the subset of the recorded commands that meet the predicate
|
|
||||||
func (f *FakeRuleStore) GetRecordedCommands(predicate func(cmd interface{}) (interface{}, bool)) []interface{} {
|
|
||||||
f.mtx.Lock()
|
|
||||||
defer f.mtx.Unlock()
|
|
||||||
|
|
||||||
result := make([]interface{}, 0, len(f.RecordedOps))
|
|
||||||
for _, op := range f.RecordedOps {
|
|
||||||
cmd, ok := predicate(op)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
result = append(result, cmd)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeRuleStore) DeleteAlertRulesByUID(_ context.Context, orgID int64, UIDs ...string) error {
|
|
||||||
f.RecordedOps = append(f.RecordedOps, GenericRecordedQuery{
|
|
||||||
Name: "DeleteAlertRulesByUID",
|
|
||||||
Params: []interface{}{orgID, UIDs},
|
|
||||||
})
|
|
||||||
|
|
||||||
rules := f.Rules[orgID]
|
|
||||||
|
|
||||||
var result = make([]*models.AlertRule, 0, len(rules))
|
|
||||||
|
|
||||||
for _, rule := range rules {
|
|
||||||
add := true
|
|
||||||
for _, UID := range UIDs {
|
|
||||||
if rule.UID == UID {
|
|
||||||
add = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if add {
|
|
||||||
result = append(result, rule)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f.Rules[orgID] = result
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeRuleStore) GetAlertRuleByUID(_ context.Context, q *models.GetAlertRuleByUIDQuery) error {
|
|
||||||
f.mtx.Lock()
|
|
||||||
defer f.mtx.Unlock()
|
|
||||||
f.RecordedOps = append(f.RecordedOps, *q)
|
|
||||||
if err := f.Hook(*q); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rules, ok := f.Rules[q.OrgID]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, rule := range rules {
|
|
||||||
if rule.UID == q.UID {
|
|
||||||
q.Result = rule
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeRuleStore) GetAlertRulesGroupByRuleUID(_ context.Context, q *models.GetAlertRulesGroupByRuleUIDQuery) error {
|
|
||||||
f.mtx.Lock()
|
|
||||||
defer f.mtx.Unlock()
|
|
||||||
f.RecordedOps = append(f.RecordedOps, *q)
|
|
||||||
if err := f.Hook(*q); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rules, ok := f.Rules[q.OrgID]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var selected *models.AlertRule
|
|
||||||
for _, rule := range rules {
|
|
||||||
if rule.UID == q.UID {
|
|
||||||
selected = rule
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if selected == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, rule := range rules {
|
|
||||||
if rule.GetGroupKey() == selected.GetGroupKey() {
|
|
||||||
q.Result = append(q.Result, rule)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeRuleStore) ListAlertRules(_ context.Context, q *models.ListAlertRulesQuery) error {
|
|
||||||
f.mtx.Lock()
|
|
||||||
defer f.mtx.Unlock()
|
|
||||||
f.RecordedOps = append(f.RecordedOps, *q)
|
|
||||||
|
|
||||||
if err := f.Hook(*q); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
hasDashboard := func(r *models.AlertRule, dashboardUID string, panelID int64) bool {
|
|
||||||
if dashboardUID != "" {
|
|
||||||
if r.DashboardUID == nil || *r.DashboardUID != dashboardUID {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if panelID > 0 {
|
|
||||||
if r.PanelID == nil || *r.PanelID != panelID {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
hasNamespace := func(r *models.AlertRule, namespaceUIDs []string) bool {
|
|
||||||
if len(namespaceUIDs) > 0 {
|
|
||||||
var ok bool
|
|
||||||
for _, uid := range q.NamespaceUIDs {
|
|
||||||
if uid == r.NamespaceUID {
|
|
||||||
ok = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, r := range f.Rules[q.OrgID] {
|
|
||||||
if !hasDashboard(r, q.DashboardUID, q.PanelID) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !hasNamespace(r, q.NamespaceUIDs) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if q.RuleGroup != "" && r.RuleGroup != q.RuleGroup {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
q.Result = append(q.Result, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeRuleStore) GetUserVisibleNamespaces(_ context.Context, orgID int64, _ *user.SignedInUser) (map[string]*models2.Folder, error) {
|
|
||||||
f.mtx.Lock()
|
|
||||||
defer f.mtx.Unlock()
|
|
||||||
|
|
||||||
namespacesMap := map[string]*models2.Folder{}
|
|
||||||
|
|
||||||
_, ok := f.Rules[orgID]
|
|
||||||
if !ok {
|
|
||||||
return namespacesMap, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, folder := range f.Folders[orgID] {
|
|
||||||
namespacesMap[folder.Uid] = folder
|
|
||||||
}
|
|
||||||
return namespacesMap, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeRuleStore) GetNamespaceByTitle(_ context.Context, title string, orgID int64, _ *user.SignedInUser, _ bool) (*models2.Folder, error) {
|
|
||||||
folders := f.Folders[orgID]
|
|
||||||
for _, folder := range folders {
|
|
||||||
if folder.Title == title {
|
|
||||||
return folder, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeRuleStore) GetNamespaceByUID(_ context.Context, uid string, orgID int64, _ *user.SignedInUser) (*models2.Folder, error) {
|
|
||||||
f.RecordedOps = append(f.RecordedOps, GenericRecordedQuery{
|
|
||||||
Name: "GetNamespaceByUID",
|
|
||||||
Params: []interface{}{orgID, uid},
|
|
||||||
})
|
|
||||||
|
|
||||||
folders := f.Folders[orgID]
|
|
||||||
for _, folder := range folders {
|
|
||||||
if folder.Uid == uid {
|
|
||||||
return folder, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeRuleStore) UpdateAlertRules(_ context.Context, q []models.UpdateRule) error {
|
|
||||||
f.mtx.Lock()
|
|
||||||
defer f.mtx.Unlock()
|
|
||||||
f.RecordedOps = append(f.RecordedOps, q)
|
|
||||||
if err := f.Hook(q); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeRuleStore) InsertAlertRules(_ context.Context, q []models.AlertRule) (map[string]int64, error) {
|
|
||||||
f.mtx.Lock()
|
|
||||||
defer f.mtx.Unlock()
|
|
||||||
f.RecordedOps = append(f.RecordedOps, q)
|
|
||||||
ids := make(map[string]int64, len(q))
|
|
||||||
if err := f.Hook(q); err != nil {
|
|
||||||
return ids, err
|
|
||||||
}
|
|
||||||
return ids, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeRuleStore) InTransaction(ctx context.Context, fn func(c context.Context) error) error {
|
|
||||||
return fn(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeRuleStore) GetRuleGroupInterval(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string) (int64, error) {
|
|
||||||
f.mtx.Lock()
|
|
||||||
defer f.mtx.Unlock()
|
|
||||||
for _, rule := range f.Rules[orgID] {
|
|
||||||
if rule.RuleGroup == ruleGroup && rule.NamespaceUID == namespaceUID {
|
|
||||||
return rule.IntervalSeconds, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0, ErrAlertRuleGroupNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeRuleStore) UpdateRuleGroup(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string, interval int64) error {
|
|
||||||
f.mtx.Lock()
|
|
||||||
defer f.mtx.Unlock()
|
|
||||||
for _, rule := range f.Rules[orgID] {
|
|
||||||
if rule.RuleGroup == ruleGroup && rule.NamespaceUID == namespaceUID {
|
|
||||||
rule.IntervalSeconds = interval
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FakeRuleStore) IncreaseVersionForAllRulesInNamespace(_ context.Context, orgID int64, namespaceUID string) ([]models.AlertRuleKeyWithVersion, error) {
|
|
||||||
f.mtx.Lock()
|
|
||||||
defer f.mtx.Unlock()
|
|
||||||
|
|
||||||
f.RecordedOps = append(f.RecordedOps, GenericRecordedQuery{
|
|
||||||
Name: "IncreaseVersionForAllRulesInNamespace",
|
|
||||||
Params: []interface{}{orgID, namespaceUID},
|
|
||||||
})
|
|
||||||
|
|
||||||
var result []models.AlertRuleKeyWithVersion
|
|
||||||
|
|
||||||
for _, rule := range f.Rules[orgID] {
|
|
||||||
if rule.NamespaceUID == namespaceUID && rule.OrgID == orgID {
|
|
||||||
rule.Version++
|
|
||||||
rule.Updated = TimeNow()
|
|
||||||
result = append(result, models.AlertRuleKeyWithVersion{
|
|
||||||
Version: rule.Version,
|
|
||||||
AlertRuleKey: rule.GetKey(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFakeAdminConfigStore(t *testing.T) *FakeAdminConfigStore {
|
func NewFakeAdminConfigStore(t *testing.T) *FakeAdminConfigStore {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
return &FakeAdminConfigStore{Configs: map[int64]*models.AdminConfiguration{}}
|
return &FakeAdminConfigStore{Configs: map[int64]*models.AdminConfiguration{}}
|
||||||
|
341
pkg/services/ngalert/tests/fakes/rules.go
Normal file
341
pkg/services/ngalert/tests/fakes/rules.go
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
package fakes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
models2 "github.com/grafana/grafana/pkg/models"
|
||||||
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||||
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
|
"github.com/grafana/grafana/pkg/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FakeRuleStore mocks the RuleStore of the scheduler.
|
||||||
|
type RuleStore struct {
|
||||||
|
t *testing.T
|
||||||
|
mtx sync.Mutex
|
||||||
|
// OrgID -> RuleGroup -> Namespace -> Rules
|
||||||
|
Rules map[int64][]*models.AlertRule
|
||||||
|
Hook func(cmd interface{}) error // use Hook if you need to intercept some query and return an error
|
||||||
|
RecordedOps []interface{}
|
||||||
|
Folders map[int64][]*models2.Folder
|
||||||
|
}
|
||||||
|
|
||||||
|
type GenericRecordedQuery struct {
|
||||||
|
Name string
|
||||||
|
Params []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRuleStore(t *testing.T) *RuleStore {
|
||||||
|
return &RuleStore{
|
||||||
|
t: t,
|
||||||
|
Rules: map[int64][]*models.AlertRule{},
|
||||||
|
Hook: func(interface{}) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Folders: map[int64][]*models2.Folder{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutRule puts the rule in the Rules map. If there are existing rule in the same namespace, they will be overwritten
|
||||||
|
func (f *RuleStore) PutRule(_ context.Context, rules ...*models.AlertRule) {
|
||||||
|
f.mtx.Lock()
|
||||||
|
defer f.mtx.Unlock()
|
||||||
|
mainloop:
|
||||||
|
for _, r := range rules {
|
||||||
|
rgs := f.Rules[r.OrgID]
|
||||||
|
for idx, rulePtr := range rgs {
|
||||||
|
if rulePtr.UID == r.UID {
|
||||||
|
rgs[idx] = r
|
||||||
|
continue mainloop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rgs = append(rgs, r)
|
||||||
|
f.Rules[r.OrgID] = rgs
|
||||||
|
|
||||||
|
var existing *models2.Folder
|
||||||
|
folders := f.Folders[r.OrgID]
|
||||||
|
for _, folder := range folders {
|
||||||
|
if folder.Uid == r.NamespaceUID {
|
||||||
|
existing = folder
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if existing == nil {
|
||||||
|
folders = append(folders, &models2.Folder{
|
||||||
|
Id: rand.Int63(),
|
||||||
|
Uid: r.NamespaceUID,
|
||||||
|
Title: "TEST-FOLDER-" + util.GenerateShortUID(),
|
||||||
|
})
|
||||||
|
f.Folders[r.OrgID] = folders
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRecordedCommands filters recorded commands using predicate function. Returns the subset of the recorded commands that meet the predicate
|
||||||
|
func (f *RuleStore) GetRecordedCommands(predicate func(cmd interface{}) (interface{}, bool)) []interface{} {
|
||||||
|
f.mtx.Lock()
|
||||||
|
defer f.mtx.Unlock()
|
||||||
|
|
||||||
|
result := make([]interface{}, 0, len(f.RecordedOps))
|
||||||
|
for _, op := range f.RecordedOps {
|
||||||
|
cmd, ok := predicate(op)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
result = append(result, cmd)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RuleStore) DeleteAlertRulesByUID(_ context.Context, orgID int64, UIDs ...string) error {
|
||||||
|
f.RecordedOps = append(f.RecordedOps, GenericRecordedQuery{
|
||||||
|
Name: "DeleteAlertRulesByUID",
|
||||||
|
Params: []interface{}{orgID, UIDs},
|
||||||
|
})
|
||||||
|
|
||||||
|
rules := f.Rules[orgID]
|
||||||
|
|
||||||
|
var result = make([]*models.AlertRule, 0, len(rules))
|
||||||
|
|
||||||
|
for _, rule := range rules {
|
||||||
|
add := true
|
||||||
|
for _, UID := range UIDs {
|
||||||
|
if rule.UID == UID {
|
||||||
|
add = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if add {
|
||||||
|
result = append(result, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Rules[orgID] = result
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RuleStore) GetAlertRuleByUID(_ context.Context, q *models.GetAlertRuleByUIDQuery) error {
|
||||||
|
f.mtx.Lock()
|
||||||
|
defer f.mtx.Unlock()
|
||||||
|
f.RecordedOps = append(f.RecordedOps, *q)
|
||||||
|
if err := f.Hook(*q); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rules, ok := f.Rules[q.OrgID]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rule := range rules {
|
||||||
|
if rule.UID == q.UID {
|
||||||
|
q.Result = rule
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RuleStore) GetAlertRulesGroupByRuleUID(_ context.Context, q *models.GetAlertRulesGroupByRuleUIDQuery) error {
|
||||||
|
f.mtx.Lock()
|
||||||
|
defer f.mtx.Unlock()
|
||||||
|
f.RecordedOps = append(f.RecordedOps, *q)
|
||||||
|
if err := f.Hook(*q); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rules, ok := f.Rules[q.OrgID]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var selected *models.AlertRule
|
||||||
|
for _, rule := range rules {
|
||||||
|
if rule.UID == q.UID {
|
||||||
|
selected = rule
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if selected == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rule := range rules {
|
||||||
|
if rule.GetGroupKey() == selected.GetGroupKey() {
|
||||||
|
q.Result = append(q.Result, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RuleStore) ListAlertRules(_ context.Context, q *models.ListAlertRulesQuery) error {
|
||||||
|
f.mtx.Lock()
|
||||||
|
defer f.mtx.Unlock()
|
||||||
|
f.RecordedOps = append(f.RecordedOps, *q)
|
||||||
|
|
||||||
|
if err := f.Hook(*q); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
hasDashboard := func(r *models.AlertRule, dashboardUID string, panelID int64) bool {
|
||||||
|
if dashboardUID != "" {
|
||||||
|
if r.DashboardUID == nil || *r.DashboardUID != dashboardUID {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if panelID > 0 {
|
||||||
|
if r.PanelID == nil || *r.PanelID != panelID {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
hasNamespace := func(r *models.AlertRule, namespaceUIDs []string) bool {
|
||||||
|
if len(namespaceUIDs) > 0 {
|
||||||
|
var ok bool
|
||||||
|
for _, uid := range q.NamespaceUIDs {
|
||||||
|
if uid == r.NamespaceUID {
|
||||||
|
ok = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range f.Rules[q.OrgID] {
|
||||||
|
if !hasDashboard(r, q.DashboardUID, q.PanelID) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !hasNamespace(r, q.NamespaceUIDs) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if q.RuleGroup != "" && r.RuleGroup != q.RuleGroup {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
q.Result = append(q.Result, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RuleStore) GetUserVisibleNamespaces(_ context.Context, orgID int64, _ *user.SignedInUser) (map[string]*models2.Folder, error) {
|
||||||
|
f.mtx.Lock()
|
||||||
|
defer f.mtx.Unlock()
|
||||||
|
|
||||||
|
namespacesMap := map[string]*models2.Folder{}
|
||||||
|
|
||||||
|
_, ok := f.Rules[orgID]
|
||||||
|
if !ok {
|
||||||
|
return namespacesMap, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, folder := range f.Folders[orgID] {
|
||||||
|
namespacesMap[folder.Uid] = folder
|
||||||
|
}
|
||||||
|
return namespacesMap, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RuleStore) GetNamespaceByTitle(_ context.Context, title string, orgID int64, _ *user.SignedInUser, _ bool) (*models2.Folder, error) {
|
||||||
|
folders := f.Folders[orgID]
|
||||||
|
for _, folder := range folders {
|
||||||
|
if folder.Title == title {
|
||||||
|
return folder, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RuleStore) GetNamespaceByUID(_ context.Context, uid string, orgID int64, _ *user.SignedInUser) (*models2.Folder, error) {
|
||||||
|
f.RecordedOps = append(f.RecordedOps, GenericRecordedQuery{
|
||||||
|
Name: "GetNamespaceByUID",
|
||||||
|
Params: []interface{}{orgID, uid},
|
||||||
|
})
|
||||||
|
|
||||||
|
folders := f.Folders[orgID]
|
||||||
|
for _, folder := range folders {
|
||||||
|
if folder.Uid == uid {
|
||||||
|
return folder, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RuleStore) UpdateAlertRules(_ context.Context, q []models.UpdateRule) error {
|
||||||
|
f.mtx.Lock()
|
||||||
|
defer f.mtx.Unlock()
|
||||||
|
f.RecordedOps = append(f.RecordedOps, q)
|
||||||
|
if err := f.Hook(q); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RuleStore) InsertAlertRules(_ context.Context, q []models.AlertRule) (map[string]int64, error) {
|
||||||
|
f.mtx.Lock()
|
||||||
|
defer f.mtx.Unlock()
|
||||||
|
f.RecordedOps = append(f.RecordedOps, q)
|
||||||
|
ids := make(map[string]int64, len(q))
|
||||||
|
if err := f.Hook(q); err != nil {
|
||||||
|
return ids, err
|
||||||
|
}
|
||||||
|
return ids, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RuleStore) InTransaction(ctx context.Context, fn func(c context.Context) error) error {
|
||||||
|
return fn(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RuleStore) GetRuleGroupInterval(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string) (int64, error) {
|
||||||
|
f.mtx.Lock()
|
||||||
|
defer f.mtx.Unlock()
|
||||||
|
for _, rule := range f.Rules[orgID] {
|
||||||
|
if rule.RuleGroup == ruleGroup && rule.NamespaceUID == namespaceUID {
|
||||||
|
return rule.IntervalSeconds, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, errors.New("rule group not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RuleStore) UpdateRuleGroup(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string, interval int64) error {
|
||||||
|
f.mtx.Lock()
|
||||||
|
defer f.mtx.Unlock()
|
||||||
|
for _, rule := range f.Rules[orgID] {
|
||||||
|
if rule.RuleGroup == ruleGroup && rule.NamespaceUID == namespaceUID {
|
||||||
|
rule.IntervalSeconds = interval
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RuleStore) IncreaseVersionForAllRulesInNamespace(_ context.Context, orgID int64, namespaceUID string) ([]models.AlertRuleKeyWithVersion, error) {
|
||||||
|
f.mtx.Lock()
|
||||||
|
defer f.mtx.Unlock()
|
||||||
|
|
||||||
|
f.RecordedOps = append(f.RecordedOps, GenericRecordedQuery{
|
||||||
|
Name: "IncreaseVersionForAllRulesInNamespace",
|
||||||
|
Params: []interface{}{orgID, namespaceUID},
|
||||||
|
})
|
||||||
|
|
||||||
|
var result []models.AlertRuleKeyWithVersion
|
||||||
|
|
||||||
|
for _, rule := range f.Rules[orgID] {
|
||||||
|
if rule.NamespaceUID == namespaceUID && rule.OrgID == orgID {
|
||||||
|
rule.Version++
|
||||||
|
rule.Updated = time.Now()
|
||||||
|
result = append(result, models.AlertRuleKeyWithVersion{
|
||||||
|
Version: rule.Version,
|
||||||
|
AlertRuleKey: rule.GetKey(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user