diff --git a/pkg/services/ngalert/api/api_alertmanager_test.go b/pkg/services/ngalert/api/api_alertmanager_test.go index 2673269ca2f..970e822add0 100644 --- a/pkg/services/ngalert/api/api_alertmanager_test.go +++ b/pkg/services/ngalert/api/api_alertmanager_test.go @@ -663,7 +663,7 @@ func createMultiOrgAlertmanager(t *testing.T) *notifier.MultiOrgAlertmanager { } configStore := notifier.NewFakeConfigStore(t, configs) orgStore := notifier.NewFakeOrgStore(t, []int64{1, 2, 3}) - provStore := provisioning.NewFakeProvisioningStore() + provStore := ngfakes.NewFakeProvisioningStore() tmpDir := t.TempDir() kvStore := ngfakes.NewFakeKVStore(t) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) diff --git a/pkg/services/ngalert/api/api_ruler_test.go b/pkg/services/ngalert/api/api_ruler_test.go index 7777349c940..4da5f7265f6 100644 --- a/pkg/services/ngalert/api/api_ruler_test.go +++ b/pkg/services/ngalert/api/api_ruler_test.go @@ -86,7 +86,7 @@ func TestRouteDeleteAlertRules(t *testing.T) { }) t.Run("delete only non-provisioned groups that user is authorized", func(t *testing.T) { ruleStore := initFakeRuleStore(t) - provisioningStore := provisioning.NewFakeProvisioningStore() + provisioningStore := fakes.NewFakeProvisioningStore() authorizedRulesInFolder := models.GenerateAlertRulesSmallNonEmpty(models.AlertRuleGen(withOrgID(orgID), withNamespace(folder), withGroup("authz_"+util.GenerateShortUID()))) @@ -109,7 +109,7 @@ func TestRouteDeleteAlertRules(t *testing.T) { }) t.Run("return 400 if all rules user can access are provisioned", func(t *testing.T) { ruleStore := initFakeRuleStore(t) - provisioningStore := provisioning.NewFakeProvisioningStore() + provisioningStore := fakes.NewFakeProvisioningStore() provisionedRulesInFolder := models.GenerateAlertRulesSmallNonEmpty(models.AlertRuleGen(withOrgID(orgID), withNamespace(folder), withGroup(util.GenerateShortUID()))) err := provisioningStore.SetProvenance(context.Background(), provisionedRulesInFolder[0], orgID, models.ProvenanceAPI) @@ -158,7 +158,7 @@ func TestRouteDeleteAlertRules(t *testing.T) { }) t.Run("return 400 if group is provisioned", func(t *testing.T) { ruleStore := initFakeRuleStore(t) - provisioningStore := provisioning.NewFakeProvisioningStore() + provisioningStore := fakes.NewFakeProvisioningStore() provisionedRulesInFolder := models.GenerateAlertRulesSmallNonEmpty(models.AlertRuleGen(withOrgID(orgID), withNamespace(folder), withGroup(groupName))) err := provisioningStore.SetProvenance(context.Background(), provisionedRulesInFolder[0], orgID, models.ProvenanceAPI) @@ -598,7 +598,7 @@ func createService(store *fakes.RuleStore) *RulerSrv { xactManager: store, store: store, QuotaService: nil, - provenanceStore: provisioning.NewFakeProvisioningStore(), + provenanceStore: fakes.NewFakeProvisioningStore(), log: log.New("test"), cfg: &setting.UnifiedAlertingSettings{ BaseInterval: 10 * time.Second, diff --git a/pkg/services/ngalert/notifier/multiorg_alertmanager_remote_test.go b/pkg/services/ngalert/notifier/multiorg_alertmanager_remote_test.go index a5a3f795e50..827173630c0 100644 --- a/pkg/services/ngalert/notifier/multiorg_alertmanager_remote_test.go +++ b/pkg/services/ngalert/notifier/multiorg_alertmanager_remote_test.go @@ -12,7 +12,6 @@ import ( "github.com/grafana/grafana/pkg/services/ngalert/metrics" "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/grafana/grafana/pkg/services/ngalert/notifier" - "github.com/grafana/grafana/pkg/services/ngalert/provisioning" "github.com/grafana/grafana/pkg/services/ngalert/remote" remoteClient "github.com/grafana/grafana/pkg/services/ngalert/remote/client" ngfakes "github.com/grafana/grafana/pkg/services/ngalert/tests/fakes" @@ -93,7 +92,7 @@ func TestMultiorgAlertmanager_RemoteSecondaryMode(t *testing.T) { configStore, notifier.NewFakeOrgStore(t, []int64{1}), kvStore, - provisioning.NewFakeProvisioningStore(), + ngfakes.NewFakeProvisioningStore(), secretsService.GetDecryptedValue, m.GetMultiOrgAlertmanagerMetrics(), nil, diff --git a/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go b/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go index 68d9310f4ae..0698e5701be 100644 --- a/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go +++ b/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go @@ -17,7 +17,6 @@ import ( "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/services/ngalert/metrics" "github.com/grafana/grafana/pkg/services/ngalert/models" - "github.com/grafana/grafana/pkg/services/ngalert/provisioning" "github.com/grafana/grafana/pkg/services/ngalert/store" ngfakes "github.com/grafana/grafana/pkg/services/ngalert/tests/fakes" "github.com/grafana/grafana/pkg/services/secrets/fakes" @@ -33,7 +32,7 @@ func TestMultiOrgAlertmanager_SyncAlertmanagersForOrgs(t *testing.T) { tmpDir := t.TempDir() kvStore := ngfakes.NewFakeKVStore(t) - provStore := provisioning.NewFakeProvisioningStore() + provStore := ngfakes.NewFakeProvisioningStore() secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) decryptFn := secretsService.GetDecryptedValue reg := prometheus.NewPedanticRegistry() @@ -167,7 +166,7 @@ func TestMultiOrgAlertmanager_SyncAlertmanagersForOrgsWithFailures(t *testing.T) tmpDir := t.TempDir() kvStore := ngfakes.NewFakeKVStore(t) - provStore := provisioning.NewFakeProvisioningStore() + provStore := ngfakes.NewFakeProvisioningStore() secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) decryptFn := secretsService.GetDecryptedValue reg := prometheus.NewPedanticRegistry() @@ -261,7 +260,7 @@ func TestMultiOrgAlertmanager_AlertmanagerFor(t *testing.T) { UnifiedAlerting: setting.UnifiedAlertingSettings{AlertmanagerConfigPollInterval: 3 * time.Minute, DefaultConfiguration: setting.GetAlertmanagerDefaultConfiguration()}, // do not poll in tests. } kvStore := ngfakes.NewFakeKVStore(t) - provStore := provisioning.NewFakeProvisioningStore() + provStore := ngfakes.NewFakeProvisioningStore() secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) decryptFn := secretsService.GetDecryptedValue reg := prometheus.NewPedanticRegistry() @@ -313,7 +312,7 @@ func TestMultiOrgAlertmanager_ActivateHistoricalConfiguration(t *testing.T) { UnifiedAlerting: setting.UnifiedAlertingSettings{AlertmanagerConfigPollInterval: 3 * time.Minute, DefaultConfiguration: defaultConfig}, // do not poll in tests. } kvStore := ngfakes.NewFakeKVStore(t) - provStore := provisioning.NewFakeProvisioningStore() + provStore := ngfakes.NewFakeProvisioningStore() secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) decryptFn := secretsService.GetDecryptedValue reg := prometheus.NewPedanticRegistry() diff --git a/pkg/services/ngalert/provisioning/contactpoints_test.go b/pkg/services/ngalert/provisioning/contactpoints_test.go index 8bb9606806a..38f9bfa983b 100644 --- a/pkg/services/ngalert/provisioning/contactpoints_test.go +++ b/pkg/services/ngalert/provisioning/contactpoints_test.go @@ -19,6 +19,7 @@ import ( "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/grafana/grafana/pkg/services/ngalert/notifier" + "github.com/grafana/grafana/pkg/services/ngalert/tests/fakes" "github.com/grafana/grafana/pkg/services/secrets" "github.com/grafana/grafana/pkg/services/secrets/database" "github.com/grafana/grafana/pkg/services/secrets/manager" @@ -36,21 +37,15 @@ func TestContactPointService(t *testing.T) { cps, err := sut.GetContactPoints(context.Background(), cpsQuery(1), nil) require.NoError(t, err) - require.Len(t, cps, 1) - require.Equal(t, "slack receiver", cps[0].Name) + require.Len(t, cps, 2) + require.Equal(t, "grafana-default-email", cps[0].Name) + require.Equal(t, "slack receiver", cps[1].Name) }) t.Run("service filters contact points by name", func(t *testing.T) { sut := createContactPointServiceSut(t, secretsService) - newCp := createTestContactPoint() - _, err := sut.CreateContactPoint(context.Background(), 1, newCp, models.ProvenanceAPI) - require.NoError(t, err) - q := ContactPointQuery{ - OrgID: 1, - Name: "slack receiver", - } - cps, err := sut.GetContactPoints(context.Background(), q, nil) + cps, err := sut.GetContactPoints(context.Background(), cpsQueryWithName(1, "slack receiver"), nil) require.NoError(t, err) require.Len(t, cps, 1) @@ -66,9 +61,9 @@ func TestContactPointService(t *testing.T) { cps, err := sut.GetContactPoints(context.Background(), cpsQuery(1), nil) require.NoError(t, err) - require.Len(t, cps, 2) - require.Equal(t, "test-contact-point", cps[1].Name) - require.Equal(t, "slack", cps[1].Type) + require.Len(t, cps, 3) + require.Equal(t, "test-contact-point", cps[2].Name) + require.Equal(t, "slack", cps[2].Type) }) t.Run("it's possible to use a custom uid", func(t *testing.T) { @@ -80,10 +75,10 @@ func TestContactPointService(t *testing.T) { _, err := sut.CreateContactPoint(context.Background(), 1, newCp, models.ProvenanceAPI) require.NoError(t, err) - cps, err := sut.GetContactPoints(context.Background(), cpsQuery(1), nil) + cps, err := sut.GetContactPoints(context.Background(), cpsQueryWithName(1, newCp.Name), nil) require.NoError(t, err) - require.Len(t, cps, 2) - require.Equal(t, customUID, cps[1].UID) + require.Len(t, cps, 1) + require.Equal(t, customUID, cps[0].UID) }) t.Run("it's not possible to use invalid UID", func(t *testing.T) { @@ -216,19 +211,19 @@ func TestContactPointService(t *testing.T) { newCp, err := sut.CreateContactPoint(context.Background(), 1, newCp, test.from) require.NoError(t, err) - cps, err := sut.GetContactPoints(context.Background(), cpsQuery(1), nil) + cps, err := sut.GetContactPoints(context.Background(), cpsQueryWithName(1, newCp.Name), nil) require.NoError(t, err) - require.Equal(t, newCp.UID, cps[1].UID) - require.Equal(t, test.from, models.Provenance(cps[1].Provenance)) + require.Equal(t, newCp.UID, cps[0].UID) + require.Equal(t, test.from, models.Provenance(cps[0].Provenance)) err = sut.UpdateContactPoint(context.Background(), 1, newCp, test.to) if test.errNil { require.NoError(t, err) - cps, err = sut.GetContactPoints(context.Background(), cpsQuery(1), nil) + cps, err = sut.GetContactPoints(context.Background(), cpsQueryWithName(1, newCp.Name), nil) require.NoError(t, err) - require.Equal(t, newCp.UID, cps[1].UID) - require.Equal(t, test.to, models.Provenance(cps[1].Provenance)) + require.Equal(t, newCp.UID, cps[0].UID) + require.Equal(t, test.to, models.Provenance(cps[0].Provenance)) } else { require.Error(t, err, fmt.Sprintf("cannot change provenance from '%s' to '%s'", test.from, test.to)) } @@ -246,8 +241,8 @@ func TestContactPointService(t *testing.T) { _, err = sut.CreateContactPoint(context.Background(), 1, newCp, models.ProvenanceAPI) require.NoError(t, err) - fake := sut.configStore.store.(*fakeAMConfigStore) - intercepted := fake.lastSaveCommand + fake := sut.configStore.store.(*fakes.FakeAlertmanagerConfigStore) + intercepted := fake.LastSaveCommand require.Equal(t, expectedConcurrencyToken, intercepted.FetchedConfigurationHash) }) } @@ -262,9 +257,9 @@ func TestContactPointServiceDecryptRedact(t *testing.T) { cps, err := sut.GetContactPoints(context.Background(), cpsQuery(1), nil) require.NoError(t, err) - require.Len(t, cps, 1) - require.Equal(t, "slack receiver", cps[0].Name) - require.Equal(t, definitions.RedactedValue, cps[0].Settings.Get("url").MustString()) + require.Len(t, cps, 2) + require.Equal(t, "slack receiver", cps[1].Name) + require.Equal(t, definitions.RedactedValue, cps[1].Settings.Get("url").MustString()) }) t.Run("GetContactPoints errors when Decrypt = true and user does not have permissions", func(t *testing.T) { sut := createContactPointServiceSut(t, secretsService) @@ -289,7 +284,8 @@ func TestContactPointServiceDecryptRedact(t *testing.T) { sut := createContactPointServiceSut(t, secretsService) sut.ac = ac - q := cpsQuery(1) + expectedName := "slack receiver" + q := cpsQueryWithName(1, expectedName) q.Decrypt = true cps, err := sut.GetContactPoints(context.Background(), q, &user.SignedInUser{OrgID: 1, Permissions: map[int64]map[string][]string{ 1: { @@ -299,7 +295,7 @@ func TestContactPointServiceDecryptRedact(t *testing.T) { require.NoError(t, err) require.Len(t, cps, 1) - require.Equal(t, "slack receiver", cps[0].Name) + require.Equal(t, expectedName, cps[0].Name) require.Equal(t, "secure url", cps[0].Settings.Get("url").MustString()) }) } @@ -349,8 +345,8 @@ func createContactPointServiceSut(t *testing.T, secretService secrets.Service) * require.NoError(t, err) return &ContactPointService{ - configStore: &alertmanagerConfigStoreImpl{store: newFakeAMConfigStore(string(raw))}, - provenanceStore: NewFakeProvisioningStore(), + configStore: &alertmanagerConfigStoreImpl{store: fakes.NewFakeAlertmanagerConfigStore(string(raw))}, + provenanceStore: fakes.NewFakeProvisioningStore(), xact: newNopTransactionManager(), encryptionService: secretService, log: log.NewNopLogger(), @@ -373,6 +369,13 @@ func cpsQuery(orgID int64) ContactPointQuery { } } +func cpsQueryWithName(orgID int64, name string) ContactPointQuery { + return ContactPointQuery{ + OrgID: orgID, + Name: name, + } +} + func TestStitchReceivers(t *testing.T) { type testCase struct { name string diff --git a/pkg/services/ngalert/provisioning/notification_policies_test.go b/pkg/services/ngalert/provisioning/notification_policies_test.go index dc51c7f7ecf..6202848606d 100644 --- a/pkg/services/ngalert/provisioning/notification_policies_test.go +++ b/pkg/services/ngalert/provisioning/notification_policies_test.go @@ -13,6 +13,7 @@ import ( "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" "github.com/grafana/grafana/pkg/services/ngalert/models" + "github.com/grafana/grafana/pkg/services/ngalert/tests/fakes" "github.com/grafana/grafana/pkg/setting" ) @@ -44,7 +45,7 @@ func TestNotificationPolicyService(t *testing.T) { Return(nil) newRoute := createTestRoutingTree() newRoute.Routes = append(newRoute.Routes, &definitions.Route{ - Receiver: "a new receiver", + Receiver: "slack receiver", MuteTimeIntervals: []string{"not-existing"}, }) @@ -70,7 +71,7 @@ func TestNotificationPolicyService(t *testing.T) { Return(nil) newRoute := createTestRoutingTree() newRoute.Routes = append(newRoute.Routes, &definitions.Route{ - Receiver: "a new receiver", + Receiver: "slack receiver", MuteTimeIntervals: []string{"existing"}, }) @@ -88,7 +89,7 @@ func TestNotificationPolicyService(t *testing.T) { updated, err := sut.GetPolicyTree(context.Background(), 1) require.NoError(t, err) - require.Equal(t, "a new receiver", updated.Receiver) + require.Equal(t, "slack receiver", updated.Receiver) }) t.Run("not existing receiver reference will error", func(t *testing.T) { @@ -153,8 +154,8 @@ func TestNotificationPolicyService(t *testing.T) { err = sut.UpdatePolicyTree(context.Background(), 1, newRoute, models.ProvenanceAPI) require.NoError(t, err) - fake := sut.GetAMConfigStore().(*fakeAMConfigStore) - intercepted := fake.lastSaveCommand + fake := sut.GetAMConfigStore().(*fakes.FakeAlertmanagerConfigStore) + intercepted := fake.LastSaveCommand require.Equal(t, expectedConcurrencyToken, intercepted.FetchedConfigurationHash) }) @@ -186,12 +187,12 @@ func TestNotificationPolicyService(t *testing.T) { sut.configStore.store = &MockAMConfigStore{} cfg := createTestAlertingConfig() cfg.AlertmanagerConfig.Route = &definitions.Route{ - Receiver: "a new receiver", + Receiver: "slack receiver", } cfg.AlertmanagerConfig.Receivers = []*definitions.PostableApiReceiver{ { Receiver: config.Receiver{ - Name: "a new receiver", + Name: "slack receiver", }, }, // No default receiver! Only our custom one. @@ -216,8 +217,8 @@ func TestNotificationPolicyService(t *testing.T) { func createNotificationPolicyServiceSut() *NotificationPolicyService { return &NotificationPolicyService{ - configStore: &alertmanagerConfigStoreImpl{store: newFakeAMConfigStore(defaultAlertmanagerConfigJSON)}, - provenanceStore: NewFakeProvisioningStore(), + configStore: &alertmanagerConfigStoreImpl{store: fakes.NewFakeAlertmanagerConfigStore(defaultAlertmanagerConfigJSON)}, + provenanceStore: fakes.NewFakeProvisioningStore(), xact: newNopTransactionManager(), log: log.NewNopLogger(), settings: setting.UnifiedAlertingSettings{ @@ -228,7 +229,7 @@ func createNotificationPolicyServiceSut() *NotificationPolicyService { func createTestRoutingTree() definitions.Route { return definitions.Route{ - Receiver: "a new receiver", + Receiver: "slack receiver", } } @@ -238,7 +239,7 @@ func createTestAlertingConfig() *definitions.PostableUserConfig { &definitions.PostableApiReceiver{ Receiver: config.Receiver{ // default one from createTestRoutingTree() - Name: "a new receiver", + Name: "slack receiver", }, }) cfg.AlertmanagerConfig.Receivers = append(cfg.AlertmanagerConfig.Receivers, diff --git a/pkg/services/ngalert/provisioning/testing.go b/pkg/services/ngalert/provisioning/testing.go index a935805d664..fa36058e99d 100644 --- a/pkg/services/ngalert/provisioning/testing.go +++ b/pkg/services/ngalert/provisioning/testing.go @@ -2,9 +2,6 @@ package provisioning import ( "context" - "crypto/md5" - "fmt" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -31,8 +28,8 @@ const defaultAlertmanagerConfigJSON = ` "receivers": [{ "name": "grafana-default-email", "grafana_managed_receiver_configs": [{ - "uid": "", - "name": "email receiver", + "uid": "UID1", + "name": "grafana-default-email", "type": "email", "disableResolveMessage": false, "settings": { @@ -41,9 +38,9 @@ const defaultAlertmanagerConfigJSON = ` "secureFields": {} }] }, { - "name": "a new receiver", + "name": "slack receiver", "grafana_managed_receiver_configs": [{ - "uid": "", + "uid": "UID2", "name": "slack receiver", "type": "slack", "disableResolveMessage": false, @@ -55,88 +52,6 @@ const defaultAlertmanagerConfigJSON = ` } ` -type fakeAMConfigStore struct { - config models.AlertConfiguration - lastSaveCommand *models.SaveAlertmanagerConfigurationCmd -} - -func newFakeAMConfigStore(config string) *fakeAMConfigStore { - return &fakeAMConfigStore{ - config: models.AlertConfiguration{ - AlertmanagerConfiguration: config, - ConfigurationVersion: "v1", - Default: true, - OrgID: 1, - }, - lastSaveCommand: nil, - } -} - -func (f *fakeAMConfigStore) GetLatestAlertmanagerConfiguration(ctx context.Context, orgID int64) (*models.AlertConfiguration, error) { - result := &f.config - result.OrgID = orgID - result.ConfigurationHash = fmt.Sprintf("%x", md5.Sum([]byte(f.config.AlertmanagerConfiguration))) - return result, nil -} - -func (f *fakeAMConfigStore) UpdateAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error { - f.config = models.AlertConfiguration{ - AlertmanagerConfiguration: cmd.AlertmanagerConfiguration, - ConfigurationVersion: cmd.ConfigurationVersion, - Default: cmd.Default, - OrgID: cmd.OrgID, - } - f.lastSaveCommand = cmd - return nil -} - -type fakeProvisioningStore struct { - records map[int64]map[string]models.Provenance -} - -func NewFakeProvisioningStore() *fakeProvisioningStore { - return &fakeProvisioningStore{ - records: map[int64]map[string]models.Provenance{}, - } -} - -func (f *fakeProvisioningStore) GetProvenance(ctx context.Context, o models.Provisionable, org int64) (models.Provenance, error) { - if val, ok := f.records[org]; ok { - if prov, ok := val[o.ResourceID()+o.ResourceType()]; ok { - return prov, nil - } - } - return models.ProvenanceNone, nil -} - -func (f *fakeProvisioningStore) GetProvenances(ctx context.Context, orgID int64, resourceType string) (map[string]models.Provenance, error) { - results := make(map[string]models.Provenance) - if val, ok := f.records[orgID]; ok { - for k, v := range val { - if strings.HasSuffix(k, resourceType) { - results[strings.TrimSuffix(k, resourceType)] = v - } - } - } - return results, nil -} - -func (f *fakeProvisioningStore) SetProvenance(ctx context.Context, o models.Provisionable, org int64, p models.Provenance) error { - if _, ok := f.records[org]; !ok { - f.records[org] = map[string]models.Provenance{} - } - _ = f.DeleteProvenance(ctx, o, org) // delete old entries first - f.records[org][o.ResourceID()+o.ResourceType()] = p - return nil -} - -func (f *fakeProvisioningStore) DeleteProvenance(ctx context.Context, o models.Provisionable, org int64) error { - if val, ok := f.records[org]; ok { - delete(val, o.ResourceID()+o.ResourceType()) - } - return nil -} - type NopTransactionManager struct{} func newNopTransactionManager() *NopTransactionManager { diff --git a/pkg/services/ngalert/sender/router_test.go b/pkg/services/ngalert/sender/router_test.go index 042527967df..505a4f038bb 100644 --- a/pkg/services/ngalert/sender/router_test.go +++ b/pkg/services/ngalert/sender/router_test.go @@ -23,7 +23,6 @@ import ( "github.com/grafana/grafana/pkg/services/ngalert/metrics" "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/grafana/grafana/pkg/services/ngalert/notifier" - "github.com/grafana/grafana/pkg/services/ngalert/provisioning" "github.com/grafana/grafana/pkg/services/ngalert/store" "github.com/grafana/grafana/pkg/services/ngalert/tests/fakes" fake_secrets "github.com/grafana/grafana/pkg/services/secrets/fakes" @@ -411,7 +410,7 @@ func createMultiOrgAlertmanager(t *testing.T, orgs []int64) *notifier.MultiOrgAl m := metrics.NewNGAlert(registry) secretsService := secretsManager.SetupTestService(t, fake_secrets.NewFakeSecretsStore()) decryptFn := secretsService.GetDecryptedValue - moa, err := notifier.NewMultiOrgAlertmanager(cfg, cfgStore, orgStore, kvStore, provisioning.NewFakeProvisioningStore(), decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService) + moa, err := notifier.NewMultiOrgAlertmanager(cfg, cfgStore, orgStore, kvStore, fakes.NewFakeProvisioningStore(), decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService) require.NoError(t, err) require.NoError(t, moa.LoadAndSyncAlertmanagersForOrgs(context.Background())) require.Eventually(t, func() bool { diff --git a/pkg/services/ngalert/tests/fakes/config.go b/pkg/services/ngalert/tests/fakes/config.go new file mode 100644 index 00000000000..5fe396556ba --- /dev/null +++ b/pkg/services/ngalert/tests/fakes/config.go @@ -0,0 +1,44 @@ +package fakes + +import ( + "context" + "crypto/md5" + "fmt" + + "github.com/grafana/grafana/pkg/services/ngalert/models" +) + +type FakeAlertmanagerConfigStore struct { + Config models.AlertConfiguration + LastSaveCommand *models.SaveAlertmanagerConfigurationCmd +} + +func NewFakeAlertmanagerConfigStore(config string) *FakeAlertmanagerConfigStore { + return &FakeAlertmanagerConfigStore{ + Config: models.AlertConfiguration{ + AlertmanagerConfiguration: config, + ConfigurationVersion: "v1", + Default: true, + OrgID: 1, + }, + LastSaveCommand: nil, + } +} + +func (f *FakeAlertmanagerConfigStore) GetLatestAlertmanagerConfiguration(ctx context.Context, orgID int64) (*models.AlertConfiguration, error) { + result := &f.Config + result.OrgID = orgID + result.ConfigurationHash = fmt.Sprintf("%x", md5.Sum([]byte(f.Config.AlertmanagerConfiguration))) + return result, nil +} + +func (f *FakeAlertmanagerConfigStore) UpdateAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error { + f.Config = models.AlertConfiguration{ + AlertmanagerConfiguration: cmd.AlertmanagerConfiguration, + ConfigurationVersion: cmd.ConfigurationVersion, + Default: cmd.Default, + OrgID: cmd.OrgID, + } + f.LastSaveCommand = cmd + return nil +} diff --git a/pkg/services/ngalert/tests/fakes/provisioning.go b/pkg/services/ngalert/tests/fakes/provisioning.go new file mode 100644 index 00000000000..1274fa42ff6 --- /dev/null +++ b/pkg/services/ngalert/tests/fakes/provisioning.go @@ -0,0 +1,55 @@ +package fakes + +import ( + "context" + "strings" + + "github.com/grafana/grafana/pkg/services/ngalert/models" +) + +type FakeProvisioningStore struct { + Records map[int64]map[string]models.Provenance +} + +func NewFakeProvisioningStore() *FakeProvisioningStore { + return &FakeProvisioningStore{ + Records: map[int64]map[string]models.Provenance{}, + } +} + +func (f *FakeProvisioningStore) GetProvenance(ctx context.Context, o models.Provisionable, org int64) (models.Provenance, error) { + if val, ok := f.Records[org]; ok { + if prov, ok := val[o.ResourceID()+o.ResourceType()]; ok { + return prov, nil + } + } + return models.ProvenanceNone, nil +} + +func (f *FakeProvisioningStore) GetProvenances(ctx context.Context, orgID int64, resourceType string) (map[string]models.Provenance, error) { + results := make(map[string]models.Provenance) + if val, ok := f.Records[orgID]; ok { + for k, v := range val { + if strings.HasSuffix(k, resourceType) { + results[strings.TrimSuffix(k, resourceType)] = v + } + } + } + return results, nil +} + +func (f *FakeProvisioningStore) SetProvenance(ctx context.Context, o models.Provisionable, org int64, p models.Provenance) error { + if _, ok := f.Records[org]; !ok { + f.Records[org] = map[string]models.Provenance{} + } + _ = f.DeleteProvenance(ctx, o, org) // delete old entries first + f.Records[org][o.ResourceID()+o.ResourceType()] = p + return nil +} + +func (f *FakeProvisioningStore) DeleteProvenance(ctx context.Context, o models.Provisionable, org int64) error { + if val, ok := f.Records[org]; ok { + delete(val, o.ResourceID()+o.ResourceType()) + } + return nil +}