From b09ce8478e5276d58b82f971307bf5dd3c23bbd3 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Tue, 26 Apr 2022 11:28:10 -0400 Subject: [PATCH] Indicate whether routes are provisioned when GETting Alertmanager configuration (#47857) (#48286) * Test composition simplification from last PR * Policies use proper API model everywhere * Expose policy provenance in API, miss some dep injection * Complete injection * fix args * Tests for provenance value * Extract test helpers so tests are very readable * Single source adapter struct that was copied in 3 places * Drop redundant test * Resolve merge conflicts on changelog (cherry picked from commit 8310789ef1da3c1784434ba69b4ec66333d4c67f) Co-authored-by: Alexander Weaver --- pkg/services/ngalert/CHANGELOG.md | 1 + .../ngalert/api/api_alertmanager_test.go | 77 ++++++++++++++++--- pkg/services/ngalert/api/api_provisioning.go | 3 +- .../ngalert/api/api_provisioning_test.go | 16 ++-- .../definitions/provisioning_contactpoints.go | 2 +- pkg/services/ngalert/ngalert.go | 2 +- .../ngalert/notifier/alertmanager_config.go | 24 ++++++ .../ngalert/notifier/multiorg_alertmanager.go | 11 ++- .../notifier/multiorg_alertmanager_test.go | 10 ++- .../ngalert/provisioning/contactpoints.go | 24 +++--- .../provisioning/contactpoints_test.go | 2 +- .../provisioning/notification_policies.go | 51 ++++-------- .../notification_policies_test.go | 2 +- pkg/services/ngalert/provisioning/persist.go | 17 ++++ pkg/services/ngalert/provisioning/testing.go | 2 +- .../ngalert/schedule/schedule_unit_test.go | 3 +- 16 files changed, 163 insertions(+), 84 deletions(-) diff --git a/pkg/services/ngalert/CHANGELOG.md b/pkg/services/ngalert/CHANGELOG.md index 03c96b10cf6..8928cbe22e5 100644 --- a/pkg/services/ngalert/CHANGELOG.md +++ b/pkg/services/ngalert/CHANGELOG.md @@ -49,3 +49,4 @@ Scopes must have an order to ensure consistency and ease of search, this helps u - [BUGFIX] Scheduler: Fix state manager to support OK option of `AlertRule.ExecErrState` #47670 - [ENHANCEMENT] Templates: Enable the use of classic condition values in templates #46971 - [CHANGE] Notification URL points to alert view page instead of alert edit page. #47752 +- [FEATURE] Indicate whether routes are provisioned when GETting Alertmanager configuration #47857 diff --git a/pkg/services/ngalert/api/api_alertmanager_test.go b/pkg/services/ngalert/api/api_alertmanager_test.go index eec2b513e00..7a4b2cc8dde 100644 --- a/pkg/services/ngalert/api/api_alertmanager_test.go +++ b/pkg/services/ngalert/api/api_alertmanager_test.go @@ -2,6 +2,7 @@ package api import ( "context" + "encoding/json" "math/rand" "net/http" "testing" @@ -12,14 +13,17 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/accesscontrol" acMock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" + "github.com/grafana/grafana/pkg/services/featuremgmt" apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" "github.com/grafana/grafana/pkg/services/ngalert/metrics" ngmodels "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/secrets/fakes" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" "github.com/grafana/grafana/pkg/setting" @@ -208,6 +212,31 @@ func TestAlertmanagerConfig(t *testing.T) { require.Equal(t, 202, response.Status()) }) + + t.Run("when objects are not provisioned", func(t *testing.T) { + t.Run("route from GET config has no provenance", func(t *testing.T) { + sut := createSut(t, nil) + rc := createRequestCtxInOrg(1) + + response := sut.RouteGetAlertingConfig(rc) + + body := asGettableUserConfig(t, response) + require.Equal(t, ngmodels.ProvenanceNone, body.AlertmanagerConfig.Route.Provenance) + }) + }) + + t.Run("when objects are provisioned", func(t *testing.T) { + t.Run("route from GET config has expected provenance", func(t *testing.T) { + sut := createSut(t, nil) + rc := createRequestCtxInOrg(1) + setRouteProvenance(t, 1, sut.mam.ProvStore) + + response := sut.RouteGetAlertingConfig(rc) + + body := asGettableUserConfig(t, response) + require.Equal(t, ngmodels.ProvenanceAPI, body.AlertmanagerConfig.Route.Provenance) + }) + }) } func TestRouteCreateSilence(t *testing.T) { @@ -346,19 +375,16 @@ func createSut(t *testing.T, accessControl accesscontrol.AccessControl) Alertman t.Helper() mam := createMultiOrgAlertmanager(t) - configs := map[int64]*ngmodels.AlertConfiguration{ - 1: {AlertmanagerConfiguration: validConfig, OrgID: 1}, - 2: {AlertmanagerConfiguration: validConfig, OrgID: 2}, - 3: {AlertmanagerConfiguration: brokenConfig, OrgID: 3}, - } - configStore := notifier.NewFakeConfigStore(t, configs) - secrets := fakes.NewFakeSecretsService() if accessControl == nil { accessControl = acMock.New().WithDisabled() } log := log.NewNopLogger() - crypto := notifier.NewCrypto(secrets, &configStore, log) - return AlertmanagerSrv{mam: mam, crypto: crypto, ac: accessControl, log: log} + return AlertmanagerSrv{ + mam: mam, + crypto: mam.Crypto, + ac: accessControl, + log: log, + } } func createAmConfigRequest(t *testing.T) apimodels.PostableUserConfig { @@ -381,6 +407,7 @@ func createMultiOrgAlertmanager(t *testing.T) *notifier.MultiOrgAlertmanager { } configStore := notifier.NewFakeConfigStore(t, configs) orgStore := notifier.NewFakeOrgStore(t, []int64{1, 2, 3}) + provStore := provisioning.NewFakeProvisioningStore() tmpDir := t.TempDir() kvStore := notifier.NewFakeKVStore(t) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) @@ -394,9 +421,12 @@ func createMultiOrgAlertmanager(t *testing.T) *notifier.MultiOrgAlertmanager { DefaultConfiguration: setting.GetAlertmanagerDefaultConfiguration(), DisabledOrgs: map[int64]struct{}{5: {}}, }, // do not poll in tests. + IsFeatureToggleEnabled: func(key string) bool { + return key == featuremgmt.FlagAlertProvisioning + }, } - mam, err := notifier.NewMultiOrgAlertmanager(cfg, &configStore, &orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService) + mam, err := notifier.NewMultiOrgAlertmanager(cfg, &configStore, &orgStore, kvStore, provStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService) require.NoError(t, err) err = mam.LoadAndSyncAlertmanagersForOrgs(context.Background()) require.NoError(t, err) @@ -460,3 +490,30 @@ func silenceGen(mutatorFuncs ...func(*apimodels.PostableSilence)) func() apimode func withEmptyID(silence *apimodels.PostableSilence) { silence.ID = "" } + +func createRequestCtxInOrg(org int64) *models.ReqContext { + return &models.ReqContext{ + Context: &web.Context{ + Req: &http.Request{}, + }, + SignedInUser: &models.SignedInUser{ + OrgId: org, + }, + } +} + +// setRouteProvenance marks an org's routing tree as provisioned. +func setRouteProvenance(t *testing.T, org int64, ps provisioning.ProvisioningStore) { + t.Helper() + adp := provisioning.ProvenanceOrgAdapter{Inner: &apimodels.Route{}, OrgID: org} + err := ps.SetProvenance(context.Background(), adp, ngmodels.ProvenanceAPI) + require.NoError(t, err) +} + +func asGettableUserConfig(t *testing.T, r response.Response) *apimodels.GettableUserConfig { + t.Helper() + body := &apimodels.GettableUserConfig{} + err := json.Unmarshal(r.Body(), body) + require.NoError(t, err) + return body +} diff --git a/pkg/services/ngalert/api/api_provisioning.go b/pkg/services/ngalert/api/api_provisioning.go index 2b6e632c58e..c8113be9abb 100644 --- a/pkg/services/ngalert/api/api_provisioning.go +++ b/pkg/services/ngalert/api/api_provisioning.go @@ -10,7 +10,6 @@ import ( "github.com/grafana/grafana/pkg/models" apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" alerting_models "github.com/grafana/grafana/pkg/services/ngalert/models" - "github.com/grafana/grafana/pkg/services/ngalert/provisioning" "github.com/grafana/grafana/pkg/services/ngalert/store" "github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/web" @@ -30,7 +29,7 @@ type ContactPointService interface { } type NotificationPolicyService interface { - GetPolicyTree(ctx context.Context, orgID int64) (provisioning.EmbeddedRoutingTree, error) + GetPolicyTree(ctx context.Context, orgID int64) (apimodels.Route, error) UpdatePolicyTree(ctx context.Context, orgID int64, tree apimodels.Route, p alerting_models.Provenance) error } diff --git a/pkg/services/ngalert/api/api_provisioning_test.go b/pkg/services/ngalert/api/api_provisioning_test.go index 5cac3a26a1b..e618f4091d2 100644 --- a/pkg/services/ngalert/api/api_provisioning_test.go +++ b/pkg/services/ngalert/api/api_provisioning_test.go @@ -10,7 +10,6 @@ import ( "github.com/grafana/grafana/pkg/models" apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" domain "github.com/grafana/grafana/pkg/services/ngalert/models" - "github.com/grafana/grafana/pkg/services/ngalert/provisioning" "github.com/grafana/grafana/pkg/services/ngalert/store" "github.com/grafana/grafana/pkg/web" "github.com/stretchr/testify/require" @@ -120,14 +119,13 @@ func newFakeNotificationPolicyService() *fakeNotificationPolicyService { } } -func (f *fakeNotificationPolicyService) GetPolicyTree(ctx context.Context, orgID int64) (provisioning.EmbeddedRoutingTree, error) { +func (f *fakeNotificationPolicyService) GetPolicyTree(ctx context.Context, orgID int64) (apimodels.Route, error) { if orgID != 1 { - return provisioning.EmbeddedRoutingTree{}, store.ErrNoAlertmanagerConfiguration + return apimodels.Route{}, store.ErrNoAlertmanagerConfiguration } - return provisioning.EmbeddedRoutingTree{ - Route: f.tree, - Provenance: f.prov, - }, nil + result := f.tree + result.Provenance = f.prov + return result, nil } func (f *fakeNotificationPolicyService) UpdatePolicyTree(ctx context.Context, orgID int64, tree apimodels.Route, p domain.Provenance) error { @@ -141,8 +139,8 @@ func (f *fakeNotificationPolicyService) UpdatePolicyTree(ctx context.Context, or type fakeFailingNotificationPolicyService struct{} -func (f *fakeFailingNotificationPolicyService) GetPolicyTree(ctx context.Context, orgID int64) (provisioning.EmbeddedRoutingTree, error) { - return provisioning.EmbeddedRoutingTree{}, fmt.Errorf("something went wrong") +func (f *fakeFailingNotificationPolicyService) GetPolicyTree(ctx context.Context, orgID int64) (apimodels.Route, error) { + return apimodels.Route{}, fmt.Errorf("something went wrong") } func (f *fakeFailingNotificationPolicyService) UpdatePolicyTree(ctx context.Context, orgID int64, tree apimodels.Route, p domain.Provenance) error { diff --git a/pkg/services/ngalert/api/tooling/definitions/provisioning_contactpoints.go b/pkg/services/ngalert/api/tooling/definitions/provisioning_contactpoints.go index 3d86af76928..ddbcc007f2c 100644 --- a/pkg/services/ngalert/api/tooling/definitions/provisioning_contactpoints.go +++ b/pkg/services/ngalert/api/tooling/definitions/provisioning_contactpoints.go @@ -66,7 +66,7 @@ type EmbeddedContactPoint struct { Type string `json:"type" binding:"required"` Settings *simplejson.Json `json:"settings" binding:"required"` DisableResolveMessage bool `json:"disableResolveMessage"` - Provenance string `json:"provanance"` + Provenance string `json:"provenance"` } const RedactedValue = "[REDACTED]" diff --git a/pkg/services/ngalert/ngalert.go b/pkg/services/ngalert/ngalert.go index 49158bc52b5..b47cc404a33 100644 --- a/pkg/services/ngalert/ngalert.go +++ b/pkg/services/ngalert/ngalert.go @@ -99,7 +99,7 @@ func (ng *AlertNG) init() error { decryptFn := ng.SecretsService.GetDecryptedValue multiOrgMetrics := ng.Metrics.GetMultiOrgAlertmanagerMetrics() - ng.MultiOrgAlertmanager, err = notifier.NewMultiOrgAlertmanager(ng.Cfg, store, store, ng.KVStore, decryptFn, multiOrgMetrics, ng.NotificationService, log.New("ngalert.multiorg.alertmanager"), ng.SecretsService) + ng.MultiOrgAlertmanager, err = notifier.NewMultiOrgAlertmanager(ng.Cfg, store, store, ng.KVStore, store, decryptFn, multiOrgMetrics, ng.NotificationService, log.New("ngalert.multiorg.alertmanager"), ng.SecretsService) if err != nil { return err } diff --git a/pkg/services/ngalert/notifier/alertmanager_config.go b/pkg/services/ngalert/notifier/alertmanager_config.go index 7efd6561589..f3d873a9c98 100644 --- a/pkg/services/ngalert/notifier/alertmanager_config.go +++ b/pkg/services/ngalert/notifier/alertmanager_config.go @@ -5,8 +5,10 @@ import ( "errors" "fmt" + "github.com/grafana/grafana/pkg/services/featuremgmt" "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/provisioning" "github.com/grafana/grafana/pkg/services/ngalert/store" ) @@ -81,6 +83,13 @@ func (moa *MultiOrgAlertmanager) GetAlertmanagerConfiguration(ctx context.Contex result.AlertmanagerConfig.Receivers = append(result.AlertmanagerConfig.Receivers, &gettableApiReceiver) } + if moa.settings.IsFeatureToggleEnabled(featuremgmt.FlagAlertProvisioning) { + result.AlertmanagerConfig, err = moa.mergeProvenance(ctx, result.AlertmanagerConfig, org) + if err != nil { + return definitions.GettableUserConfig{}, err + } + } + return result, nil } @@ -117,3 +126,18 @@ func (moa *MultiOrgAlertmanager) ApplyAlertmanagerConfiguration(ctx context.Cont return nil } + +func (moa *MultiOrgAlertmanager) mergeProvenance(ctx context.Context, config definitions.GettableApiAlertingConfig, org int64) (definitions.GettableApiAlertingConfig, error) { + if config.Route != nil { + adp := provisioning.ProvenanceOrgAdapter{ + Inner: config.Route, + OrgID: org, + } + provenance, err := moa.ProvStore.GetProvenance(ctx, adp) + if err != nil { + return definitions.GettableApiAlertingConfig{}, err + } + config.Route.Provenance = provenance + } + return config, nil +} diff --git a/pkg/services/ngalert/notifier/multiorg_alertmanager.go b/pkg/services/ngalert/notifier/multiorg_alertmanager.go index d34677c3e44..6764619121d 100644 --- a/pkg/services/ngalert/notifier/multiorg_alertmanager.go +++ b/pkg/services/ngalert/notifier/multiorg_alertmanager.go @@ -10,6 +10,7 @@ import ( "time" "github.com/grafana/grafana/pkg/services/ngalert/notifier/channels" + "github.com/grafana/grafana/pkg/services/ngalert/provisioning" "github.com/grafana/grafana/pkg/services/notifications" "github.com/grafana/grafana/pkg/services/secrets" @@ -30,7 +31,8 @@ var ( ) type MultiOrgAlertmanager struct { - Crypto Crypto + Crypto Crypto + ProvStore provisioning.ProvisioningStore alertmanagersMtx sync.RWMutex alertmanagers map[int64]*Alertmanager @@ -53,11 +55,12 @@ type MultiOrgAlertmanager struct { } func NewMultiOrgAlertmanager(cfg *setting.Cfg, configStore store.AlertingStore, orgStore store.OrgStore, - kvStore kvstore.KVStore, decryptFn channels.GetDecryptedValueFn, m *metrics.MultiOrgAlertmanager, - ns notifications.Service, l log.Logger, s secrets.Service, + kvStore kvstore.KVStore, provStore provisioning.ProvisioningStore, decryptFn channels.GetDecryptedValueFn, + m *metrics.MultiOrgAlertmanager, ns notifications.Service, l log.Logger, s secrets.Service, ) (*MultiOrgAlertmanager, error) { moa := &MultiOrgAlertmanager{ - Crypto: NewCrypto(s, configStore, l), + Crypto: NewCrypto(s, configStore, l), + ProvStore: provStore, logger: l, settings: cfg, diff --git a/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go b/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go index 56899182532..d0f819775ff 100644 --- a/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go +++ b/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go @@ -13,6 +13,7 @@ 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/secrets/fakes" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" "github.com/grafana/grafana/pkg/setting" @@ -32,6 +33,7 @@ func TestMultiOrgAlertmanager_SyncAlertmanagersForOrgs(t *testing.T) { tmpDir := t.TempDir() kvStore := NewFakeKVStore(t) + provStore := provisioning.NewFakeProvisioningStore() secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) decryptFn := secretsService.GetDecryptedValue reg := prometheus.NewPedanticRegistry() @@ -44,7 +46,7 @@ func TestMultiOrgAlertmanager_SyncAlertmanagersForOrgs(t *testing.T) { DisabledOrgs: map[int64]struct{}{5: {}}, }, // do not poll in tests. } - mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService) + mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, provStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService) require.NoError(t, err) ctx := context.Background() @@ -157,6 +159,7 @@ func TestMultiOrgAlertmanager_SyncAlertmanagersForOrgsWithFailures(t *testing.T) tmpDir := t.TempDir() kvStore := NewFakeKVStore(t) + provStore := provisioning.NewFakeProvisioningStore() secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) decryptFn := secretsService.GetDecryptedValue reg := prometheus.NewPedanticRegistry() @@ -168,7 +171,7 @@ func TestMultiOrgAlertmanager_SyncAlertmanagersForOrgsWithFailures(t *testing.T) DefaultConfiguration: setting.GetAlertmanagerDefaultConfiguration(), }, // do not poll in tests. } - mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService) + mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, provStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService) require.NoError(t, err) ctx := context.Background() @@ -214,11 +217,12 @@ func TestMultiOrgAlertmanager_AlertmanagerFor(t *testing.T) { UnifiedAlerting: setting.UnifiedAlertingSettings{AlertmanagerConfigPollInterval: 3 * time.Minute, DefaultConfiguration: setting.GetAlertmanagerDefaultConfiguration()}, // do not poll in tests. } kvStore := NewFakeKVStore(t) + provStore := provisioning.NewFakeProvisioningStore() secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) decryptFn := secretsService.GetDecryptedValue reg := prometheus.NewPedanticRegistry() m := metrics.NewNGAlert(reg) - mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService) + mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, provStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService) require.NoError(t, err) ctx := context.Background() diff --git a/pkg/services/ngalert/provisioning/contactpoints.go b/pkg/services/ngalert/provisioning/contactpoints.go index 00b1b60aba7..83922021f0c 100644 --- a/pkg/services/ngalert/provisioning/contactpoints.go +++ b/pkg/services/ngalert/provisioning/contactpoints.go @@ -177,9 +177,9 @@ func (ecp *ContactPointService) CreateContactPoint(ctx context.Context, orgID in if err != nil { return err } - adapter := provenanceOrgAdapter{ - inner: &contactPoint, - orgID: orgID, + adapter := ProvenanceOrgAdapter{ + Inner: &contactPoint, + OrgID: orgID, } err = ecp.provenanceStore.SetProvenance(ctx, adapter, provenance) if err != nil { @@ -218,9 +218,9 @@ func (ecp *ContactPointService) UpdateContactPoint(ctx context.Context, orgID in return err } // check that provenance is not changed in a invalid way - storedProvenance, err := ecp.provenanceStore.GetProvenance(ctx, provenanceOrgAdapter{ - inner: &contactPoint, - orgID: orgID, + storedProvenance, err := ecp.provenanceStore.GetProvenance(ctx, ProvenanceOrgAdapter{ + Inner: &contactPoint, + OrgID: orgID, }) if err != nil { return err @@ -283,9 +283,9 @@ func (ecp *ContactPointService) UpdateContactPoint(ctx context.Context, orgID in if err != nil { return err } - adapter := provenanceOrgAdapter{ - inner: &contactPoint, - orgID: orgID, + adapter := ProvenanceOrgAdapter{ + Inner: &contactPoint, + OrgID: orgID, } err = ecp.provenanceStore.SetProvenance(ctx, adapter, provenance) if err != nil { @@ -330,11 +330,11 @@ func (ecp *ContactPointService) DeleteContactPoint(ctx context.Context, orgID in return err } return ecp.xact.InTransaction(ctx, func(ctx context.Context) error { - err := ecp.provenanceStore.DeleteProvenance(ctx, provenanceOrgAdapter{ - inner: &apimodels.EmbeddedContactPoint{ + err := ecp.provenanceStore.DeleteProvenance(ctx, ProvenanceOrgAdapter{ + Inner: &apimodels.EmbeddedContactPoint{ UID: uid, }, - orgID: orgID, + OrgID: orgID, }) if err != nil { return err diff --git a/pkg/services/ngalert/provisioning/contactpoints_test.go b/pkg/services/ngalert/provisioning/contactpoints_test.go index cb70fe05baa..d9c358aca33 100644 --- a/pkg/services/ngalert/provisioning/contactpoints_test.go +++ b/pkg/services/ngalert/provisioning/contactpoints_test.go @@ -178,7 +178,7 @@ func TestContactPointInUse(t *testing.T) { func createContactPointServiceSut(secretService secrets.Service) *ContactPointService { return &ContactPointService{ amStore: newFakeAMConfigStore(), - provenanceStore: newFakeProvisioningStore(), + provenanceStore: NewFakeProvisioningStore(), xact: newNopTransactionManager(), encryptionService: secretService, log: log.NewNopLogger(), diff --git a/pkg/services/ngalert/provisioning/notification_policies.go b/pkg/services/ngalert/provisioning/notification_policies.go index e77b5f11aea..87582b012f8 100644 --- a/pkg/services/ngalert/provisioning/notification_policies.go +++ b/pkg/services/ngalert/provisioning/notification_policies.go @@ -25,47 +25,39 @@ func NewNotificationPolicyService(am AMConfigStore, prov ProvisioningStore, xact } } -// TODO: move to Swagger codegen -type EmbeddedRoutingTree struct { - definitions.Route - Provenance models.Provenance -} - func (nps *NotificationPolicyService) GetAMConfigStore() AMConfigStore { return nps.amStore } -func (nps *NotificationPolicyService) GetPolicyTree(ctx context.Context, orgID int64) (EmbeddedRoutingTree, error) { +func (nps *NotificationPolicyService) GetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) { q := models.GetLatestAlertmanagerConfigurationQuery{ OrgID: orgID, } err := nps.amStore.GetLatestAlertmanagerConfiguration(ctx, &q) if err != nil { - return EmbeddedRoutingTree{}, err + return definitions.Route{}, err } cfg, err := DeserializeAlertmanagerConfig([]byte(q.Result.AlertmanagerConfiguration)) if err != nil { - return EmbeddedRoutingTree{}, err + return definitions.Route{}, err } if cfg.AlertmanagerConfig.Config.Route == nil { - return EmbeddedRoutingTree{}, fmt.Errorf("no route present in current alertmanager config") + return definitions.Route{}, fmt.Errorf("no route present in current alertmanager config") } - adapter := provenanceOrgAdapter{ - inner: cfg.AlertmanagerConfig.Route, - orgID: orgID, + adapter := ProvenanceOrgAdapter{ + Inner: cfg.AlertmanagerConfig.Route, + OrgID: orgID, } provenance, err := nps.provenanceStore.GetProvenance(ctx, adapter) if err != nil { - return EmbeddedRoutingTree{}, err + return definitions.Route{}, err } - result := EmbeddedRoutingTree{ - Route: *cfg.AlertmanagerConfig.Route, - Provenance: provenance, - } + result := *cfg.AlertmanagerConfig.Route + result.Provenance = provenance return result, nil } @@ -103,9 +95,9 @@ func (nps *NotificationPolicyService) UpdatePolicyTree(ctx context.Context, orgI if err != nil { return err } - adapter := provenanceOrgAdapter{ - inner: &tree, - orgID: orgID, + adapter := ProvenanceOrgAdapter{ + Inner: &tree, + OrgID: orgID, } err = nps.provenanceStore.SetProvenance(ctx, adapter, p) if err != nil { @@ -119,20 +111,3 @@ func (nps *NotificationPolicyService) UpdatePolicyTree(ctx context.Context, orgI return nil } - -type provenanceOrgAdapter struct { - inner models.ProvisionableInOrg - orgID int64 -} - -func (a provenanceOrgAdapter) ResourceType() string { - return a.inner.ResourceType() -} - -func (a provenanceOrgAdapter) ResourceID() string { - return a.inner.ResourceID() -} - -func (a provenanceOrgAdapter) ResourceOrgID() int64 { - return a.orgID -} diff --git a/pkg/services/ngalert/provisioning/notification_policies_test.go b/pkg/services/ngalert/provisioning/notification_policies_test.go index 2a27b6b3554..2b4d4327bab 100644 --- a/pkg/services/ngalert/provisioning/notification_policies_test.go +++ b/pkg/services/ngalert/provisioning/notification_policies_test.go @@ -75,7 +75,7 @@ func TestNotificationPolicyService(t *testing.T) { func createNotificationPolicyServiceSut() *NotificationPolicyService { return &NotificationPolicyService{ amStore: newFakeAMConfigStore(), - provenanceStore: newFakeProvisioningStore(), + provenanceStore: NewFakeProvisioningStore(), xact: newNopTransactionManager(), log: log.NewNopLogger(), } diff --git a/pkg/services/ngalert/provisioning/persist.go b/pkg/services/ngalert/provisioning/persist.go index eb428055a86..0be6e093dd3 100644 --- a/pkg/services/ngalert/provisioning/persist.go +++ b/pkg/services/ngalert/provisioning/persist.go @@ -24,3 +24,20 @@ type ProvisioningStore interface { type TransactionManager interface { InTransaction(ctx context.Context, work func(ctx context.Context) error) error } + +type ProvenanceOrgAdapter struct { + Inner models.ProvisionableInOrg + OrgID int64 +} + +func (a ProvenanceOrgAdapter) ResourceType() string { + return a.Inner.ResourceType() +} + +func (a ProvenanceOrgAdapter) ResourceID() string { + return a.Inner.ResourceID() +} + +func (a ProvenanceOrgAdapter) ResourceOrgID() int64 { + return a.OrgID +} diff --git a/pkg/services/ngalert/provisioning/testing.go b/pkg/services/ngalert/provisioning/testing.go index aba31dfd513..4693460c1c8 100644 --- a/pkg/services/ngalert/provisioning/testing.go +++ b/pkg/services/ngalert/provisioning/testing.go @@ -92,7 +92,7 @@ type fakeProvisioningStore struct { records map[int64]map[string]models.Provenance } -func newFakeProvisioningStore() *fakeProvisioningStore { +func NewFakeProvisioningStore() *fakeProvisioningStore { return &fakeProvisioningStore{ records: map[int64]map[string]models.Provenance{}, } diff --git a/pkg/services/ngalert/schedule/schedule_unit_test.go b/pkg/services/ngalert/schedule/schedule_unit_test.go index 7f5f8da4cac..5882a49dc12 100644 --- a/pkg/services/ngalert/schedule/schedule_unit_test.go +++ b/pkg/services/ngalert/schedule/schedule_unit_test.go @@ -26,6 +26,7 @@ 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/sender" "github.com/grafana/grafana/pkg/services/ngalert/state" "github.com/grafana/grafana/pkg/services/ngalert/store" @@ -1015,7 +1016,7 @@ func setupScheduler(t *testing.T, rs store.RuleStore, is store.InstanceStore, ac m := metrics.NewNGAlert(registry) secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) decryptFn := secretsService.GetDecryptedValue - moa, err := notifier.NewMultiOrgAlertmanager(&setting.Cfg{}, ¬ifier.FakeConfigStore{}, ¬ifier.FakeOrgStore{}, ¬ifier.FakeKVStore{}, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService) + moa, err := notifier.NewMultiOrgAlertmanager(&setting.Cfg{}, ¬ifier.FakeConfigStore{}, ¬ifier.FakeOrgStore{}, ¬ifier.FakeKVStore{}, provisioning.NewFakeProvisioningStore(), decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService) require.NoError(t, err) schedCfg := SchedulerCfg{