From 25da759bf22b005dc716927f8bb52f7f07e85d35 Mon Sep 17 00:00:00 2001 From: Alexander Weaver <weaver.alex.d@gmail.com> Date: Wed, 18 May 2022 13:52:30 -0500 Subject: [PATCH] Indicate whether templates are provisioned (#49025) --- .../ngalert/api/api_alertmanager_test.go | 52 ++++++++++++++++++- .../api/tooling/definitions/alertmanager.go | 5 +- .../ngalert/notifier/alertmanager_config.go | 25 ++++++--- 3 files changed, 71 insertions(+), 11 deletions(-) diff --git a/pkg/services/ngalert/api/api_alertmanager_test.go b/pkg/services/ngalert/api/api_alertmanager_test.go index 51f36db2e40..304ce1e0ffd 100644 --- a/pkg/services/ngalert/api/api_alertmanager_test.go +++ b/pkg/services/ngalert/api/api_alertmanager_test.go @@ -232,6 +232,15 @@ func TestAlertmanagerConfig(t *testing.T) { body := asGettableUserConfig(t, response) require.Equal(t, ngmodels.ProvenanceNone, body.AlertmanagerConfig.Receivers[0].GrafanaManagedReceivers[0].Provenance) }) + t.Run("templates from GET config have no provenance", func(t *testing.T) { + sut := createSut(t, nil) + rc := createRequestCtxInOrg(1) + + response := sut.RouteGetAlertingConfig(rc) + + body := asGettableUserConfig(t, response) + require.Nil(t, body.TemplateFileProvenances) + }) }) t.Run("when objects are provisioned", func(t *testing.T) { @@ -265,6 +274,18 @@ func TestAlertmanagerConfig(t *testing.T) { require.Equal(t, ngmodels.ProvenanceAPI, body.AlertmanagerConfig.Receivers[0].GrafanaManagedReceivers[0].Provenance) }) + t.Run("templates from GET config have expected provenance", func(t *testing.T) { + sut := createSut(t, nil) + rc := createRequestCtxInOrg(1) + setTemplateProvenance(t, 1, "a", sut.mam.ProvStore) + + response := sut.RouteGetAlertingConfig(rc) + + body := asGettableUserConfig(t, response) + require.NotNil(t, body.TemplateFileProvenances) + require.Len(t, body.TemplateFileProvenances, 1) + require.Equal(t, ngmodels.ProvenanceAPI, body.TemplateFileProvenances["a"]) + }) }) } @@ -522,7 +543,29 @@ func createMultiOrgAlertmanager(t *testing.T) *notifier.MultiOrgAlertmanager { return mam } -var validConfig = setting.GetAlertmanagerDefaultConfiguration() +var validConfig = `{ + "template_files": { + "a": "template" + }, + "alertmanager_config": { + "route": { + "receiver": "grafana-default-email" + }, + "receivers": [{ + "name": "grafana-default-email", + "grafana_managed_receiver_configs": [{ + "uid": "", + "name": "email receiver", + "type": "email", + "isDefault": true, + "settings": { + "addresses": "<example@email.com>" + } + }] + }] + } +} +` var brokenConfig = ` "alertmanager_config": { @@ -605,6 +648,13 @@ func setContactPointProvenance(t *testing.T, orgID int64, UID string, ps provisi require.NoError(t, err) } +// setTemplateProvenance marks a template as provisioned. +func setTemplateProvenance(t *testing.T, orgID int64, name string, ps provisioning.ProvisioningStore) { + t.Helper() + err := ps.SetProvenance(context.Background(), &apimodels.MessageTemplate{Name: name}, orgID, ngmodels.ProvenanceAPI) + require.NoError(t, err) +} + func asGettableUserConfig(t *testing.T, r response.Response) *apimodels.GettableUserConfig { t.Helper() body := &apimodels.GettableUserConfig{} diff --git a/pkg/services/ngalert/api/tooling/definitions/alertmanager.go b/pkg/services/ngalert/api/tooling/definitions/alertmanager.go index bdf18d2f7d3..7b525a07478 100644 --- a/pkg/services/ngalert/api/tooling/definitions/alertmanager.go +++ b/pkg/services/ngalert/api/tooling/definitions/alertmanager.go @@ -561,8 +561,9 @@ func (c *PostableUserConfig) UnmarshalYAML(value *yaml.Node) error { // swagger:model type GettableUserConfig struct { - TemplateFiles map[string]string `yaml:"template_files" json:"template_files"` - AlertmanagerConfig GettableApiAlertingConfig `yaml:"alertmanager_config" json:"alertmanager_config"` + TemplateFiles map[string]string `yaml:"template_files" json:"template_files"` + TemplateFileProvenances map[string]models.Provenance `yaml:"template_file_provenances,omitempty" json:"template_file_provenances,omitempty"` + AlertmanagerConfig GettableApiAlertingConfig `yaml:"alertmanager_config" json:"alertmanager_config"` // amSimple stores a map[string]interface of the decoded alertmanager config. // This enables circumventing the underlying alertmanager secret type diff --git a/pkg/services/ngalert/notifier/alertmanager_config.go b/pkg/services/ngalert/notifier/alertmanager_config.go index a39beea1f38..1594ff75acf 100644 --- a/pkg/services/ngalert/notifier/alertmanager_config.go +++ b/pkg/services/ngalert/notifier/alertmanager_config.go @@ -83,7 +83,7 @@ func (moa *MultiOrgAlertmanager) GetAlertmanagerConfiguration(ctx context.Contex } if moa.settings.IsFeatureToggleEnabled(featuremgmt.FlagAlertProvisioning) { - result.AlertmanagerConfig, err = moa.mergeProvenance(ctx, result.AlertmanagerConfig, org) + result, err = moa.mergeProvenance(ctx, result, org) if err != nil { return definitions.GettableUserConfig{}, err } @@ -126,25 +126,34 @@ 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 { - provenance, err := moa.ProvStore.GetProvenance(ctx, config.Route, org) +func (moa *MultiOrgAlertmanager) mergeProvenance(ctx context.Context, config definitions.GettableUserConfig, org int64) (definitions.GettableUserConfig, error) { + if config.AlertmanagerConfig.Route != nil { + provenance, err := moa.ProvStore.GetProvenance(ctx, config.AlertmanagerConfig.Route, org) if err != nil { - return definitions.GettableApiAlertingConfig{}, err + return definitions.GettableUserConfig{}, err } - config.Route.Provenance = provenance + config.AlertmanagerConfig.Route.Provenance = provenance } + cp := definitions.EmbeddedContactPoint{} cpProvs, err := moa.ProvStore.GetProvenances(ctx, org, cp.ResourceType()) if err != nil { - return definitions.GettableApiAlertingConfig{}, err + return definitions.GettableUserConfig{}, err } - for _, receiver := range config.Receivers { + for _, receiver := range config.AlertmanagerConfig.Receivers { for _, contactPoint := range receiver.GrafanaManagedReceivers { if provenance, exists := cpProvs[contactPoint.UID]; exists { contactPoint.Provenance = provenance } } } + + tmpl := definitions.MessageTemplate{} + tmplProvs, err := moa.ProvStore.GetProvenances(ctx, org, tmpl.ResourceType()) + if err != nil { + return definitions.GettableUserConfig{}, nil + } + config.TemplateFileProvenances = tmplProvs + return config, nil }