From d0f79ee60dc3b96f310d6e9a543a2f4fe566673b Mon Sep 17 00:00:00 2001 From: Yuri Tseretyan Date: Fri, 3 Oct 2025 10:37:49 -0400 Subject: [PATCH] Alerting: Update alerting module + refactor (#111761) * update alerting module * replace compat with ones from alerting * update type references Receiver and Integration to *Status * update route in provisioning test that is invalid after recent change * use right type for LINE ingtegration --- apps/iam/go.mod | 2 +- apps/iam/go.sum | 4 +- go.mod | 2 +- go.sum | 4 +- .../ngalert/api/api_provisioning_test.go | 11 +- .../ngalert/api/compat_contact_points.go | 11 +- .../ngalert/api/compat_contact_points_test.go | 20 ++- .../api/tooling/definitions/alertmanager.go | 6 +- pkg/services/ngalert/models/receivers.go | 9 +- pkg/services/ngalert/models/receivers_test.go | 21 ++- pkg/services/ngalert/models/testing.go | 16 +- pkg/services/ngalert/notifier/alertmanager.go | 5 +- .../alertmanager_mock/Alertmanager.go | 14 +- pkg/services/ngalert/notifier/compat.go | 36 ----- pkg/services/ngalert/notifier/compat_test.go | 143 ------------------ .../notifier/legacy_storage/receivers_test.go | 13 +- .../ngalert/notifier/receiver_svc_test.go | 3 +- .../ngalert/notifier/testreceivers.go | 9 +- .../ngalert/notifier/testreceivers_test.go | 11 +- pkg/services/ngalert/provisioning/compat.go | 8 +- .../provisioning/contactpoints_test.go | 15 +- pkg/services/ngalert/remote/alertmanager.go | 5 +- .../ngalert/remote/mock/remoteAlertmanager.go | 14 +- .../test-data/provisioning-mixed-set.yaml | 21 +-- .../notifications/receivers/receiver_test.go | 33 ++-- 25 files changed, 139 insertions(+), 297 deletions(-) delete mode 100644 pkg/services/ngalert/notifier/compat_test.go diff --git a/apps/iam/go.mod b/apps/iam/go.mod index 9339a260a4b..9bdcbaa3bd9 100644 --- a/apps/iam/go.mod +++ b/apps/iam/go.mod @@ -201,7 +201,7 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect github.com/googleapis/gax-go/v2 v2.14.2 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/grafana/alerting v0.0.0-20250925200825-7a889aa4934d // indirect + github.com/grafana/alerting v0.0.0-20251002001425-eeed80da0165 // indirect github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f // indirect github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 // indirect github.com/grafana/dataplane/sdata v0.0.9 // indirect diff --git a/apps/iam/go.sum b/apps/iam/go.sum index b9188d6bd5f..52ebbdf54dd 100644 --- a/apps/iam/go.sum +++ b/apps/iam/go.sum @@ -721,8 +721,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= -github.com/grafana/alerting v0.0.0-20250925200825-7a889aa4934d h1:zzEty7HgfXbQ/RiBCJFMqaZiJlqiXuz/Zbc6/H6ksuM= -github.com/grafana/alerting v0.0.0-20250925200825-7a889aa4934d/go.mod h1:T5sitas9VhVj8/S9LeRLy6H75kTBdh/sCCqHo7gaQI8= +github.com/grafana/alerting v0.0.0-20251002001425-eeed80da0165 h1:wfehM99Xlpltl9MQx8SITkgFgHmPGqrXoBCVLk/Q6NA= +github.com/grafana/alerting v0.0.0-20251002001425-eeed80da0165/go.mod h1:VGjS5gDwWEADPP6pF/drqLxEImgeuHlEW5u8E5EfIrM= github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f h1:Cbm6OKkOcJ+7CSZsGsEJzktC/SIa5bxVeYKQLuYK86o= github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f/go.mod h1:axY0cdOg3q0TZHwpHnIz5x16xZ8ZBxJHShsSHHXcHQg= github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 h1:qEwZ+7MbPjzRvTi31iT9w7NBhKIpKwZrFbYmOZLqkwA= diff --git a/go.mod b/go.mod index 795d76c28b2..c6b9784c092 100644 --- a/go.mod +++ b/go.mod @@ -86,7 +86,7 @@ require ( github.com/googleapis/gax-go/v2 v2.14.2 // @grafana/grafana-backend-group github.com/gorilla/mux v1.8.1 // @grafana/grafana-backend-group github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // @grafana/grafana-app-platform-squad - github.com/grafana/alerting v0.0.0-20250925200825-7a889aa4934d // @grafana/alerting-backend + github.com/grafana/alerting v0.0.0-20251002001425-eeed80da0165 // @grafana/alerting-backend github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f // @grafana/identity-access-team github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 // @grafana/identity-access-team github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics diff --git a/go.sum b/go.sum index 5b9714044a1..2f8028bb05b 100644 --- a/go.sum +++ b/go.sum @@ -1585,8 +1585,8 @@ github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7Fsg github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= -github.com/grafana/alerting v0.0.0-20250925200825-7a889aa4934d h1:zzEty7HgfXbQ/RiBCJFMqaZiJlqiXuz/Zbc6/H6ksuM= -github.com/grafana/alerting v0.0.0-20250925200825-7a889aa4934d/go.mod h1:T5sitas9VhVj8/S9LeRLy6H75kTBdh/sCCqHo7gaQI8= +github.com/grafana/alerting v0.0.0-20251002001425-eeed80da0165 h1:wfehM99Xlpltl9MQx8SITkgFgHmPGqrXoBCVLk/Q6NA= +github.com/grafana/alerting v0.0.0-20251002001425-eeed80da0165/go.mod h1:VGjS5gDwWEADPP6pF/drqLxEImgeuHlEW5u8E5EfIrM= github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f h1:Cbm6OKkOcJ+7CSZsGsEJzktC/SIa5bxVeYKQLuYK86o= github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f/go.mod h1:axY0cdOg3q0TZHwpHnIz5x16xZ8ZBxJHShsSHHXcHQg= github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 h1:qEwZ+7MbPjzRvTi31iT9w7NBhKIpKwZrFbYmOZLqkwA= diff --git a/pkg/services/ngalert/api/api_provisioning_test.go b/pkg/services/ngalert/api/api_provisioning_test.go index a7dd8f1f2fe..db380834c4a 100644 --- a/pkg/services/ngalert/api/api_provisioning_test.go +++ b/pkg/services/ngalert/api/api_provisioning_test.go @@ -14,8 +14,7 @@ import ( "testing" "time" - alertingNotify "github.com/grafana/alerting/notify" - "github.com/grafana/alerting/receivers/schema" + "github.com/grafana/alerting/notify/notifytest" prometheus "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/pkg/labels" "github.com/prometheus/alertmanager/timeinterval" @@ -2033,12 +2032,12 @@ func TestApiContactPointExportSnapshot(t *testing.T) { t.Run(fmt.Sprintf("exportType=%s", exportType), func(t *testing.T) { for _, redacted := range []bool{true, false} { t.Run(fmt.Sprintf("redacted=%t", redacted), func(t *testing.T) { - allIntegrations := make([]models.Integration, 0, len(alertingNotify.AllKnownConfigsForTesting)) - for integrationType := range alertingNotify.AllKnownConfigsForTesting { + allIntegrations := make([]models.Integration, 0, len(notifytest.AllKnownV1ConfigsForTesting)) + for integrationType := range notifytest.AllKnownV1ConfigsForTesting { integration := models.IntegrationGen( models.IntegrationMuts.WithName(allIntegrationsName), - models.IntegrationMuts.WithUID(fmt.Sprintf("%s-uid", integrationType)), - models.IntegrationMuts.WithValidConfig(schema.IntegrationType(integrationType)), + models.IntegrationMuts.WithUID(fmt.Sprintf("%s-uid", strings.ToLower(string(integrationType)))), + models.IntegrationMuts.WithValidConfig(integrationType), )() integration.DisableResolveMessage = redacted allIntegrations = append(allIntegrations, integration) diff --git a/pkg/services/ngalert/api/compat_contact_points.go b/pkg/services/ngalert/api/compat_contact_points.go index e18b5c0a74a..5a55bc9ca95 100644 --- a/pkg/services/ngalert/api/compat_contact_points.go +++ b/pkg/services/ngalert/api/compat_contact_points.go @@ -7,6 +7,7 @@ import ( "strings" "unsafe" + alertingModels "github.com/grafana/alerting/models" "github.com/grafana/alerting/notify" "github.com/grafana/alerting/receivers" jsoniter "github.com/json-iterator/go" @@ -53,7 +54,7 @@ func ContactPointToContactPointExport(cp definitions.ContactPoint) (notify.APIRe len(cp.Threema) + len(cp.Victorops) + len(cp.Webhook) + len(cp.Wecom) + len(cp.Webex) + len(cp.Mqtt) - integration := make([]*notify.GrafanaIntegrationConfig, 0, contactPointsLength) + integration := make([]*alertingModels.IntegrationConfig, 0, contactPointsLength) var errs []error for _, i := range cp.Alertmanager { @@ -222,20 +223,20 @@ func ContactPointToContactPointExport(cp definitions.ContactPoint) (notify.APIRe return notify.APIReceiver{}, errors.Join(errs...) } contactPoint := notify.APIReceiver{ - ConfigReceiver: notify.ConfigReceiver{Name: cp.Name}, - GrafanaIntegrations: notify.GrafanaIntegrations{Integrations: integration}, + ConfigReceiver: notify.ConfigReceiver{Name: cp.Name}, + ReceiverConfig: alertingModels.ReceiverConfig{Integrations: integration}, } return contactPoint, nil } // marshallIntegration converts the API model integration to the storage model that contains settings in the JSON format. // The secret fields are not encrypted. -func marshallIntegration(json jsoniter.API, integrationType string, integration interface{}, disableResolveMessage *bool) (*notify.GrafanaIntegrationConfig, error) { +func marshallIntegration(json jsoniter.API, integrationType string, integration interface{}, disableResolveMessage *bool) (*alertingModels.IntegrationConfig, error) { data, err := json.Marshal(integration) if err != nil { return nil, fmt.Errorf("failed to marshall integration '%s' to JSON: %w", integrationType, err) } - e := ¬ify.GrafanaIntegrationConfig{ + e := &alertingModels.IntegrationConfig{ Type: integrationType, Settings: data, } diff --git a/pkg/services/ngalert/api/compat_contact_points_test.go b/pkg/services/ngalert/api/compat_contact_points_test.go index bda8336b0bf..ef178dd085f 100644 --- a/pkg/services/ngalert/api/compat_contact_points_test.go +++ b/pkg/services/ngalert/api/compat_contact_points_test.go @@ -7,8 +7,12 @@ import ( "testing" "github.com/google/go-cmp/cmp" + alertingmodels "github.com/grafana/alerting/models" "github.com/grafana/alerting/notify" + "github.com/grafana/alerting/notify/notifytest" + "github.com/grafana/alerting/receivers/line" receiversTesting "github.com/grafana/alerting/receivers/testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" apicompat "github.com/grafana/grafana/pkg/services/ngalert/api/compat" @@ -53,12 +57,12 @@ func TestContactPointFromContactPointExports(t *testing.T) { } // use the configs for testing because they have all fields supported by integrations - for integrationType, cfg := range notify.AllKnownConfigsForTesting { - t.Run(integrationType, func(t *testing.T) { + for integrationType, cfg := range notifytest.AllKnownV1ConfigsForTesting { + t.Run(string(integrationType), func(t *testing.T) { recCfg := ¬ify.APIReceiver{ ConfigReceiver: notify.ConfigReceiver{Name: "test-receiver"}, - GrafanaIntegrations: notify.GrafanaIntegrations{ - Integrations: []*notify.GrafanaIntegrationConfig{ + ReceiverConfig: alertingmodels.ReceiverConfig{ + Integrations: []*alertingmodels.IntegrationConfig{ cfg.GetRawNotifierConfig("test"), }, }, @@ -87,9 +91,15 @@ func TestContactPointFromContactPointExports(t *testing.T) { } if integrationType != "webhook" { // Many notifiers now support HTTPClientConfig but only Webhook currently has it enabled in schema. - //TODO: Remove this once HTTPClientConfig is added to other schemas. + // TODO: Remove this once HTTPClientConfig is added to other schemas. pathFilters = append(pathFilters, "HTTPClientConfig") } + if integrationType == line.Type { + for _, l := range actual.LineConfigs { + assert.Equal(t, "line", l.Type) + l.Type = string(line.Type) + } + } pathFilter := cmp.FilterPath(func(path cmp.Path) bool { for _, filter := range pathFilters { if strings.Contains(path.String(), filter) { diff --git a/pkg/services/ngalert/api/tooling/definitions/alertmanager.go b/pkg/services/ngalert/api/tooling/definitions/alertmanager.go index 5c33ad658fe..530264dc287 100644 --- a/pkg/services/ngalert/api/tooling/definitions/alertmanager.go +++ b/pkg/services/ngalert/api/tooling/definitions/alertmanager.go @@ -603,15 +603,15 @@ type AlertGroups = amv2.AlertGroups type AlertGroup = amv2.AlertGroup -type Receiver = alertingmodels.Receiver +type Receiver = alertingmodels.ReceiverStatus // swagger:response receiversResponse type ReceiversResponse struct { // in:body - Body []alertingmodels.Receiver + Body []alertingmodels.ReceiverStatus } -type Integration = alertingmodels.Integration +type Integration = alertingmodels.IntegrationStatus // swagger:parameters RouteGetAMAlerts RouteGetAMAlertGroups RouteGetGrafanaAMAlerts RouteGetGrafanaAMAlertGroups type AlertsParams struct { diff --git a/pkg/services/ngalert/models/receivers.go b/pkg/services/ngalert/models/receivers.go index 1f892147938..08734b0f56b 100644 --- a/pkg/services/ngalert/models/receivers.go +++ b/pkg/services/ngalert/models/receivers.go @@ -12,6 +12,7 @@ import ( "sort" "strings" + "github.com/grafana/alerting/models" alertingNotify "github.com/grafana/alerting/notify" "github.com/grafana/alerting/receivers/schema" ) @@ -572,7 +573,7 @@ func (integration *Integration) Validate(decryptFn DecryptFn) error { return err } - return ValidateIntegration(context.Background(), alertingNotify.GrafanaIntegrationConfig{ + return ValidateIntegration(context.Background(), models.IntegrationConfig{ UID: decrypted.UID, Name: decrypted.Name, Type: decrypted.Config.Type, @@ -582,7 +583,7 @@ func (integration *Integration) Validate(decryptFn DecryptFn) error { }, alertingNotify.NoopDecrypt) } -func ValidateIntegration(ctx context.Context, integration alertingNotify.GrafanaIntegrationConfig, decryptFunc alertingNotify.GetDecryptedValueFn) error { +func ValidateIntegration(ctx context.Context, integration models.IntegrationConfig, decryptFunc alertingNotify.GetDecryptedValueFn) error { if integration.Type == "" { return fmt.Errorf("type should not be an empty string") } @@ -591,8 +592,8 @@ func ValidateIntegration(ctx context.Context, integration alertingNotify.Grafana } _, err := alertingNotify.BuildReceiverConfiguration(ctx, &alertingNotify.APIReceiver{ - GrafanaIntegrations: alertingNotify.GrafanaIntegrations{ - Integrations: []*alertingNotify.GrafanaIntegrationConfig{&integration}, + ReceiverConfig: models.ReceiverConfig{ + Integrations: []*models.IntegrationConfig{&integration}, }, }, alertingNotify.DecodeSecretsFromBase64, decryptFunc) if err != nil { diff --git a/pkg/services/ngalert/models/receivers_test.go b/pkg/services/ngalert/models/receivers_test.go index 0c6c08c3d93..785fffd49be 100644 --- a/pkg/services/ngalert/models/receivers_test.go +++ b/pkg/services/ngalert/models/receivers_test.go @@ -6,6 +6,7 @@ import ( "testing" alertingNotify "github.com/grafana/alerting/notify" + "github.com/grafana/alerting/notify/notifytest" "github.com/grafana/alerting/receivers/schema" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -40,8 +41,7 @@ func TestReceiver_EncryptDecrypt(t *testing.T) { encryptFn := Base64Enrypt decryptnFn := Base64Decrypt // Test that all known integration types encrypt and decrypt their secrets. - for it := range alertingNotify.AllKnownConfigsForTesting { - integrationType := schema.IntegrationType(it) + for integrationType := range notifytest.AllKnownV1ConfigsForTesting { t.Run(string(integrationType), func(t *testing.T) { decrypedIntegration := IntegrationGen(IntegrationMuts.WithValidConfig(integrationType))() encrypted := decrypedIntegration.Clone() @@ -76,8 +76,7 @@ func TestIntegration_Redact(t *testing.T) { return "TESTREDACTED" } // Test that all known integration types redact their secrets. - for it := range alertingNotify.AllKnownConfigsForTesting { - integrationType := schema.IntegrationType(it) + for integrationType := range notifytest.AllKnownV1ConfigsForTesting { t.Run(string(integrationType), func(t *testing.T) { validIntegration := IntegrationGen(IntegrationMuts.WithValidConfig(integrationType))() @@ -106,8 +105,7 @@ func TestIntegration_Validate(t *testing.T) { testutil.SkipIntegrationTestInShortMode(t) // Test that all known integration types are valid. - for it := range alertingNotify.AllKnownConfigsForTesting { - integrationType := schema.IntegrationType(it) + for integrationType := range notifytest.AllKnownV1ConfigsForTesting { t.Run(string(integrationType), func(t *testing.T) { validIntegration := IntegrationGen(IntegrationMuts.WithValidConfig(integrationType))() assert.NoError(t, validIntegration.Encrypt(Base64Enrypt)) @@ -242,8 +240,7 @@ func TestIntegration_WithExistingSecureFields(t *testing.T) { func TestSecretsIntegrationConfig(t *testing.T) { // Test that all known integration types have a config and correctly mark their secrets as secure. - for it := range alertingNotify.AllKnownConfigsForTesting { - integrationType := schema.IntegrationType(it) + for integrationType := range notifytest.AllKnownV1ConfigsForTesting { t.Run(string(integrationType), func(t *testing.T) { schemaType, ok := alertingNotify.GetSchemaForIntegration(integrationType) require.True(t, ok) @@ -272,8 +269,8 @@ func TestSecretsIntegrationConfig(t *testing.T) { } t.Run("Unknown version returns error", func(t *testing.T) { - for s := range maps.Keys(alertingNotify.AllKnownConfigsForTesting) { - schemaType, _ := alertingNotify.GetSchemaForIntegration(schema.IntegrationType(s)) + for s := range maps.Keys(notifytest.AllKnownV1ConfigsForTesting) { + schemaType, _ := alertingNotify.GetSchemaForIntegration(s) _, err := IntegrationConfigFromSchema(schemaType, "unknown") require.Error(t, err) return @@ -285,8 +282,8 @@ func TestIntegration_SecureFields(t *testing.T) { testutil.SkipIntegrationTestInShortMode(t) // Test that all known integration types have a config and correctly mark their secrets as secure. - for it := range alertingNotify.AllKnownConfigsForTesting { - integrationType := schema.IntegrationType(it) + for it := range notifytest.AllKnownV1ConfigsForTesting { + integrationType := it t.Run(string(integrationType), func(t *testing.T) { t.Run("contains SecureSettings", func(t *testing.T) { validIntegration := IntegrationGen(IntegrationMuts.WithValidConfig(integrationType))() diff --git a/pkg/services/ngalert/models/testing.go b/pkg/services/ngalert/models/testing.go index 2164ca8f86f..0fd681b693c 100644 --- a/pkg/services/ngalert/models/testing.go +++ b/pkg/services/ngalert/models/testing.go @@ -13,6 +13,7 @@ import ( "github.com/go-openapi/strfmt" "github.com/google/uuid" alertingNotify "github.com/grafana/alerting/notify" + "github.com/grafana/alerting/notify/notifytest" "github.com/grafana/alerting/receivers/schema" "github.com/grafana/alerting/receivers/webex" "github.com/grafana/grafana-plugin-sdk-go/data" @@ -1270,7 +1271,7 @@ func CopyIntegrationWith(r Integration, mutators ...Mutator[Integration]) Integr func IntegrationGen(mutators ...Mutator[Integration]) func() Integration { return func() Integration { name := util.GenerateShortUID() - randomIntegrationType, _ := randomMapKey(alertingNotify.AllKnownConfigsForTesting) + randomIntegrationType, _ := randomMapKey(notifytest.AllKnownV1ConfigsForTesting) c := Integration{ UID: util.GenerateShortUID(), @@ -1280,7 +1281,7 @@ func IntegrationGen(mutators ...Mutator[Integration]) func() Integration { SecureSettings: make(map[string]string), } - IntegrationMuts.WithValidConfig(schema.IntegrationType(randomIntegrationType))(&c) + IntegrationMuts.WithValidConfig(randomIntegrationType)(&c) for _, mutator := range mutators { mutator(&c) @@ -1317,7 +1318,11 @@ func (n IntegrationMutators) WithName(name string) Mutator[Integration] { func (n IntegrationMutators) WithValidConfig(integrationType schema.IntegrationType) Mutator[Integration] { return func(c *Integration) { // TODO add support for v0 integrations - config := alertingNotify.AllKnownConfigsForTesting[string(integrationType)].GetRawNotifierConfig(c.Name) + ncfg, ok := notifytest.AllKnownV1ConfigsForTesting[integrationType] + if !ok { + panic(fmt.Sprintf("unknown integration type: %s", integrationType)) + } + config := ncfg.GetRawNotifierConfig(c.Name) typeSchema, _ := alertingNotify.GetSchemaForIntegration(integrationType) integrationConfig, _ := IntegrationConfigFromSchema(typeSchema, schema.V1) c.Config = integrationConfig @@ -1337,7 +1342,10 @@ func (n IntegrationMutators) WithValidConfig(integrationType schema.IntegrationT func (n IntegrationMutators) WithInvalidConfig(integrationType schema.IntegrationType) Mutator[Integration] { return func(c *Integration) { - typeSchema, _ := alertingNotify.GetSchemaForIntegration(integrationType) + typeSchema, ok := alertingNotify.GetSchemaForIntegration(integrationType) + if !ok { + panic(fmt.Sprintf("unknown integration type: %s", integrationType)) + } c.Config, _ = IntegrationConfigFromSchema(typeSchema, schema.V1) c.Settings = map[string]interface{}{} c.SecureSettings = map[string]string{} diff --git a/pkg/services/ngalert/notifier/alertmanager.go b/pkg/services/ngalert/notifier/alertmanager.go index 06c5b5e0cce..f4454d87c5f 100644 --- a/pkg/services/ngalert/notifier/alertmanager.go +++ b/pkg/services/ngalert/notifier/alertmanager.go @@ -9,6 +9,7 @@ import ( "strconv" "time" + "github.com/grafana/alerting/models" alertingNotify "github.com/grafana/alerting/notify" "github.com/grafana/alerting/notify/nfstatus" "github.com/prometheus/alertmanager/config" @@ -365,7 +366,7 @@ func (am *alertmanager) applyConfig(ctx context.Context, cfg *apimodels.Postable return false, nil } - receivers := PostableApiAlertingConfigToApiReceivers(amConfig) + receivers := alertingNotify.PostableAPIReceiversToAPIReceivers(amConfig.Receivers) for _, recv := range receivers { err = patchNewSecureFields(ctx, recv, alertingNotify.DecodeSecretsFromBase64, am.decryptFn) if err != nil { @@ -406,7 +407,7 @@ func patchNewSecureFields(ctx context.Context, api *alertingNotify.APIReceiver, return nil } -func patchSettingsFromSecureSettings(ctx context.Context, integration *alertingNotify.GrafanaIntegrationConfig, key string, decode alertingNotify.DecodeSecretsFn, decrypt alertingNotify.GetDecryptedValueFn) error { +func patchSettingsFromSecureSettings(ctx context.Context, integration *models.IntegrationConfig, key string, decode alertingNotify.DecodeSecretsFn, decrypt alertingNotify.GetDecryptedValueFn) error { if _, ok := integration.SecureSettings[key]; !ok { return nil } diff --git a/pkg/services/ngalert/notifier/alertmanager_mock/Alertmanager.go b/pkg/services/ngalert/notifier/alertmanager_mock/Alertmanager.go index 20f4e14d0ab..e4ec918e59d 100644 --- a/pkg/services/ngalert/notifier/alertmanager_mock/Alertmanager.go +++ b/pkg/services/ngalert/notifier/alertmanager_mock/Alertmanager.go @@ -309,23 +309,23 @@ func (_c *AlertmanagerMock_GetAlerts_Call) RunAndReturn(run func(context.Context } // GetReceivers provides a mock function with given fields: ctx -func (_m *AlertmanagerMock) GetReceivers(ctx context.Context) ([]alertingmodels.Receiver, error) { +func (_m *AlertmanagerMock) GetReceivers(ctx context.Context) ([]alertingmodels.ReceiverStatus, error) { ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for GetReceivers") } - var r0 []alertingmodels.Receiver + var r0 []alertingmodels.ReceiverStatus var r1 error - if rf, ok := ret.Get(0).(func(context.Context) ([]alertingmodels.Receiver, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context) ([]alertingmodels.ReceiverStatus, error)); ok { return rf(ctx) } - if rf, ok := ret.Get(0).(func(context.Context) []alertingmodels.Receiver); ok { + if rf, ok := ret.Get(0).(func(context.Context) []alertingmodels.ReceiverStatus); ok { r0 = rf(ctx) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]alertingmodels.Receiver) + r0 = ret.Get(0).([]alertingmodels.ReceiverStatus) } } @@ -356,12 +356,12 @@ func (_c *AlertmanagerMock_GetReceivers_Call) Run(run func(ctx context.Context)) return _c } -func (_c *AlertmanagerMock_GetReceivers_Call) Return(_a0 []alertingmodels.Receiver, _a1 error) *AlertmanagerMock_GetReceivers_Call { +func (_c *AlertmanagerMock_GetReceivers_Call) Return(_a0 []alertingmodels.ReceiverStatus, _a1 error) *AlertmanagerMock_GetReceivers_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *AlertmanagerMock_GetReceivers_Call) RunAndReturn(run func(context.Context) ([]alertingmodels.Receiver, error)) *AlertmanagerMock_GetReceivers_Call { +func (_c *AlertmanagerMock_GetReceivers_Call) RunAndReturn(run func(context.Context) ([]alertingmodels.ReceiverStatus, error)) *AlertmanagerMock_GetReceivers_Call { _c.Call.Return(run) return _c } diff --git a/pkg/services/ngalert/notifier/compat.go b/pkg/services/ngalert/notifier/compat.go index 9b2dccb8099..63c6ed7d7bb 100644 --- a/pkg/services/ngalert/notifier/compat.go +++ b/pkg/services/ngalert/notifier/compat.go @@ -1,47 +1,11 @@ package notifier import ( - "encoding/json" - alertingNotify "github.com/grafana/alerting/notify" - apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" "github.com/grafana/grafana/pkg/services/ngalert/models" ) -func PostableGrafanaReceiverToGrafanaIntegrationConfig(p *apimodels.PostableGrafanaReceiver) *alertingNotify.GrafanaIntegrationConfig { - return &alertingNotify.GrafanaIntegrationConfig{ - UID: p.UID, - Name: p.Name, - Type: p.Type, - DisableResolveMessage: p.DisableResolveMessage, - Settings: json.RawMessage(p.Settings), - SecureSettings: p.SecureSettings, - } -} - -func PostableApiReceiverToApiReceiver(r *apimodels.PostableApiReceiver) *alertingNotify.APIReceiver { - integrations := alertingNotify.GrafanaIntegrations{ - Integrations: make([]*alertingNotify.GrafanaIntegrationConfig, 0, len(r.GrafanaManagedReceivers)), - } - for _, cfg := range r.GrafanaManagedReceivers { - integrations.Integrations = append(integrations.Integrations, PostableGrafanaReceiverToGrafanaIntegrationConfig(cfg)) - } - - return &alertingNotify.APIReceiver{ - ConfigReceiver: r.Receiver, - GrafanaIntegrations: integrations, - } -} - -func PostableApiAlertingConfigToApiReceivers(c apimodels.PostableApiAlertingConfig) []*alertingNotify.APIReceiver { - apiReceivers := make([]*alertingNotify.APIReceiver, 0, len(c.Receivers)) - for _, receiver := range c.Receivers { - apiReceivers = append(apiReceivers, PostableApiReceiverToApiReceiver(receiver)) - } - return apiReceivers -} - // Silence-specific compat functions to convert between grafana/alerting and model types. func GettableSilenceToSilence(s alertingNotify.GettableSilence) *models.Silence { diff --git a/pkg/services/ngalert/notifier/compat_test.go b/pkg/services/ngalert/notifier/compat_test.go deleted file mode 100644 index b3a2ff8508a..00000000000 --- a/pkg/services/ngalert/notifier/compat_test.go +++ /dev/null @@ -1,143 +0,0 @@ -package notifier - -import ( - "encoding/json" - "testing" - - alertingNotify "github.com/grafana/alerting/notify" - "github.com/prometheus/alertmanager/config" - "github.com/stretchr/testify/require" - - apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" -) - -func TestPostableGrafanaReceiverToGrafanaIntegrationConfig(t *testing.T) { - r := &apimodels.PostableGrafanaReceiver{ - UID: "test-uid", - Name: "test-name", - Type: "slack", - DisableResolveMessage: false, - Settings: apimodels.RawMessage(`{ "data" : "test" }`), - SecureSettings: map[string]string{ - "test": "data", - }, - } - actual := PostableGrafanaReceiverToGrafanaIntegrationConfig(r) - require.Equal(t, alertingNotify.GrafanaIntegrationConfig{ - UID: "test-uid", - Name: "test-name", - Type: "slack", - DisableResolveMessage: false, - Settings: json.RawMessage(`{ "data" : "test" }`), - SecureSettings: map[string]string{ - "test": "data", - }, - }, *actual) -} - -func TestPostableApiReceiverToApiReceiver(t *testing.T) { - t.Run("returns empty when no receivers", func(t *testing.T) { - r := &apimodels.PostableApiReceiver{ - Receiver: config.Receiver{ - Name: "test-receiver", - }, - } - actual := PostableApiReceiverToApiReceiver(r) - require.Empty(t, actual.Integrations) - require.Equal(t, r.Receiver, actual.ConfigReceiver) - }) - t.Run("converts receivers", func(t *testing.T) { - r := &apimodels.PostableApiReceiver{ - Receiver: config.Receiver{ - Name: "test-receiver", - }, - PostableGrafanaReceivers: apimodels.PostableGrafanaReceivers{ - GrafanaManagedReceivers: []*apimodels.PostableGrafanaReceiver{ - { - UID: "test-uid", - Name: "test-name", - Type: "slack", - DisableResolveMessage: false, - Settings: apimodels.RawMessage(`{ "data" : "test" }`), - SecureSettings: map[string]string{ - "test": "data", - }, - }, - { - UID: "test-uid2", - Name: "test-name2", - Type: "webhook", - DisableResolveMessage: false, - Settings: apimodels.RawMessage(`{ "data2" : "test2" }`), - SecureSettings: map[string]string{ - "test2": "data2", - }, - }, - }, - }, - } - actual := PostableApiReceiverToApiReceiver(r) - require.Len(t, actual.Integrations, 2) - require.Equal(t, r.Receiver, actual.ConfigReceiver) - require.Equal(t, *PostableGrafanaReceiverToGrafanaIntegrationConfig(r.GrafanaManagedReceivers[0]), *actual.Integrations[0]) - require.Equal(t, *PostableGrafanaReceiverToGrafanaIntegrationConfig(r.GrafanaManagedReceivers[1]), *actual.Integrations[1]) - }) -} - -func TestPostableApiAlertingConfigToApiReceivers(t *testing.T) { - t.Run("returns empty when no receivers", func(t *testing.T) { - r := apimodels.PostableApiAlertingConfig{ - Config: apimodels.Config{}, - } - actual := PostableApiAlertingConfigToApiReceivers(r) - require.Empty(t, actual) - }) - c := apimodels.PostableApiAlertingConfig{ - Config: apimodels.Config{}, - Receivers: []*apimodels.PostableApiReceiver{ - { - Receiver: config.Receiver{ - Name: "test-receiver", - }, - PostableGrafanaReceivers: apimodels.PostableGrafanaReceivers{ - GrafanaManagedReceivers: []*apimodels.PostableGrafanaReceiver{ - { - UID: "test-uid", - Name: "test-name", - Type: "slack", - DisableResolveMessage: false, - Settings: apimodels.RawMessage(`{ "data" : "test" }`), - SecureSettings: map[string]string{ - "test": "data", - }, - }, - }, - }, - }, - { - Receiver: config.Receiver{ - Name: "test-receiver2", - }, - PostableGrafanaReceivers: apimodels.PostableGrafanaReceivers{ - GrafanaManagedReceivers: []*apimodels.PostableGrafanaReceiver{ - { - UID: "test-uid2", - Name: "test-name1", - Type: "slack", - DisableResolveMessage: false, - Settings: apimodels.RawMessage(`{ "data" : "test" }`), - SecureSettings: map[string]string{ - "test": "data", - }, - }, - }, - }, - }, - }, - } - actual := PostableApiAlertingConfigToApiReceivers(c) - - require.Len(t, actual, 2) - require.Equal(t, PostableApiReceiverToApiReceiver(c.Receivers[0]), actual[0]) - require.Equal(t, PostableApiReceiverToApiReceiver(c.Receivers[1]), actual[1]) -} diff --git a/pkg/services/ngalert/notifier/legacy_storage/receivers_test.go b/pkg/services/ngalert/notifier/legacy_storage/receivers_test.go index 72ce37763aa..a020b833de8 100644 --- a/pkg/services/ngalert/notifier/legacy_storage/receivers_test.go +++ b/pkg/services/ngalert/notifier/legacy_storage/receivers_test.go @@ -8,6 +8,7 @@ import ( "github.com/grafana/alerting/definition" "github.com/grafana/alerting/notify" + "github.com/grafana/alerting/notify/notifytest" "github.com/grafana/alerting/receivers/schema" "github.com/grafana/alerting/receivers/webhook" "github.com/prometheus/alertmanager/config" @@ -92,7 +93,7 @@ func TestDeleteReceiver(t *testing.T) { } func TestCreateReceiver(t *testing.T) { - rawCfg := notify.AllKnownConfigsForTesting[string(webhook.Type)] + rawCfg := notifytest.AllKnownV1ConfigsForTesting[webhook.Type] typeSchema, _ := notify.GetSchemaForIntegration(webhook.Type) cfgSchema, err := models.IntegrationConfigFromSchema(typeSchema, schema.V1) require.NoError(t, err) @@ -199,7 +200,7 @@ func TestCreateReceiver(t *testing.T) { } func TestUpdateReceiver(t *testing.T) { - rawCfg := notify.AllKnownConfigsForTesting[string(webhook.Type)] + rawCfg := notifytest.AllKnownV1ConfigsForTesting[webhook.Type] typeSchema, _ := notify.GetSchemaForIntegration(webhook.Type) cfgSchema, err := models.IntegrationConfigFromSchema(typeSchema, schema.V1) require.NoError(t, err) @@ -300,7 +301,7 @@ func TestUpdateReceiver(t *testing.T) { } func TestGetReceiver(t *testing.T) { - rawCfg := notify.AllKnownConfigsForTesting[string(webhook.Type)] + rawCfg := notifytest.AllKnownV1ConfigsForTesting[webhook.Type] typeSchema, _ := notify.GetSchemaForIntegration(webhook.Type) cfgSchema, err := models.IntegrationConfigFromSchema(typeSchema, schema.V1) require.NoError(t, err) @@ -491,7 +492,7 @@ func getConfigRevisionForTest() *ConfigRevision { { UID: "integration-uid-1", Type: "webhook", - Settings: definitions.RawMessage(notify.AllKnownConfigsForTesting["webhook"].Config), + Settings: definitions.RawMessage(notifytest.AllKnownV1ConfigsForTesting["webhook"].Config), }, }, }, @@ -503,7 +504,7 @@ func getConfigRevisionForTest() *ConfigRevision { { UID: "integration-uid-2", Type: "webhook", - Settings: definitions.RawMessage(notify.AllKnownConfigsForTesting["webhook"].Config), + Settings: definitions.RawMessage(notifytest.AllKnownV1ConfigsForTesting["webhook"].Config), }, }, }, @@ -515,7 +516,7 @@ func getConfigRevisionForTest() *ConfigRevision { { UID: "integration-uid-3", Type: "email", - Settings: definitions.RawMessage(notify.AllKnownConfigsForTesting["email"].Config), + Settings: definitions.RawMessage(notifytest.AllKnownV1ConfigsForTesting["email"].Config), }, }, }, diff --git a/pkg/services/ngalert/notifier/receiver_svc_test.go b/pkg/services/ngalert/notifier/receiver_svc_test.go index 5cf9146bb1c..8816124334d 100644 --- a/pkg/services/ngalert/notifier/receiver_svc_test.go +++ b/pkg/services/ngalert/notifier/receiver_svc_test.go @@ -7,6 +7,7 @@ import ( "strings" "testing" + "github.com/grafana/alerting/receivers/line" "github.com/prometheus/alertmanager/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -352,7 +353,7 @@ func TestReceiverService_Create(t *testing.T) { slackIntegration := models.IntegrationGen(models.IntegrationMuts.WithName("test receiver"), models.IntegrationMuts.WithValidConfig("slack"))() emailIntegration := models.IntegrationGen(models.IntegrationMuts.WithName("test receiver"), models.IntegrationMuts.WithValidConfig("email"))() - lineIntegration := models.IntegrationGen(models.IntegrationMuts.WithName("test receiver"), models.IntegrationMuts.WithValidConfig("line"))() + lineIntegration := models.IntegrationGen(models.IntegrationMuts.WithName("test receiver"), models.IntegrationMuts.WithValidConfig(line.Type))() baseReceiver := models.ReceiverGen(models.ReceiverMuts.WithName("test receiver"), models.ReceiverMuts.WithIntegrations(slackIntegration))() for _, tc := range []struct { diff --git a/pkg/services/ngalert/notifier/testreceivers.go b/pkg/services/ngalert/notifier/testreceivers.go index 187caab480b..41bd2a181c7 100644 --- a/pkg/services/ngalert/notifier/testreceivers.go +++ b/pkg/services/ngalert/notifier/testreceivers.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" + "github.com/grafana/alerting/models" alertingNotify "github.com/grafana/alerting/notify" v2 "github.com/prometheus/alertmanager/api/v2" @@ -13,9 +14,9 @@ import ( func (am *alertmanager) TestReceivers(ctx context.Context, c apimodels.TestReceiversConfigBodyParams) (*alertingNotify.TestReceiversResult, int, error) { receivers := make([]*alertingNotify.APIReceiver, 0, len(c.Receivers)) for _, r := range c.Receivers { - integrations := make([]*alertingNotify.GrafanaIntegrationConfig, 0, len(r.GrafanaManagedReceivers)) + integrations := make([]*models.IntegrationConfig, 0, len(r.GrafanaManagedReceivers)) for _, gr := range r.GrafanaManagedReceivers { - integrations = append(integrations, &alertingNotify.GrafanaIntegrationConfig{ + integrations = append(integrations, &models.IntegrationConfig{ UID: gr.UID, Name: gr.Name, Type: gr.Type, @@ -26,7 +27,7 @@ func (am *alertmanager) TestReceivers(ctx context.Context, c apimodels.TestRecei } recv := &alertingNotify.APIReceiver{ ConfigReceiver: r.Receiver, - GrafanaIntegrations: alertingNotify.GrafanaIntegrations{ + ReceiverConfig: models.ReceiverConfig{ Integrations: integrations, }, } @@ -52,5 +53,5 @@ func (am *alertmanager) TestReceivers(ctx context.Context, c apimodels.TestRecei } func (am *alertmanager) GetReceivers(_ context.Context) ([]apimodels.Receiver, error) { - return am.Base.GetReceivers(), nil + return am.Base.GetReceiversStatus(), nil } diff --git a/pkg/services/ngalert/notifier/testreceivers_test.go b/pkg/services/ngalert/notifier/testreceivers_test.go index 6ee01b9b9fe..b367a8500ea 100644 --- a/pkg/services/ngalert/notifier/testreceivers_test.go +++ b/pkg/services/ngalert/notifier/testreceivers_test.go @@ -6,13 +6,14 @@ import ( "net/url" "testing" + "github.com/grafana/alerting/models" alertingNotify "github.com/grafana/alerting/notify" "github.com/stretchr/testify/require" ) func TestInvalidReceiverError_Error(t *testing.T) { e := alertingNotify.IntegrationValidationError{ - Integration: &alertingNotify.GrafanaIntegrationConfig{ + Integration: &models.IntegrationConfig{ Name: "test", Type: "test-type", UID: "uid", @@ -24,7 +25,7 @@ func TestInvalidReceiverError_Error(t *testing.T) { func TestReceiverTimeoutError_Error(t *testing.T) { e := alertingNotify.IntegrationTimeoutError{ - Integration: &alertingNotify.GrafanaIntegrationConfig{ + Integration: &models.IntegrationConfig{ Name: "test", UID: "uid", }, @@ -45,7 +46,7 @@ func (e timeoutError) Timeout() bool { func TestProcessNotifierError(t *testing.T) { t.Run("assert ReceiverTimeoutError is returned for context deadline exceeded", func(t *testing.T) { - r := &alertingNotify.GrafanaIntegrationConfig{ + r := &models.IntegrationConfig{ Name: "test", UID: "uid", } @@ -56,7 +57,7 @@ func TestProcessNotifierError(t *testing.T) { }) t.Run("assert ReceiverTimeoutError is returned for *url.Error timeout", func(t *testing.T) { - r := &alertingNotify.GrafanaIntegrationConfig{ + r := &models.IntegrationConfig{ Name: "test", UID: "uid", } @@ -72,7 +73,7 @@ func TestProcessNotifierError(t *testing.T) { }) t.Run("assert unknown error is returned unmodified", func(t *testing.T) { - r := &alertingNotify.GrafanaIntegrationConfig{ + r := &models.IntegrationConfig{ Name: "test", UID: "uid", } diff --git a/pkg/services/ngalert/provisioning/compat.go b/pkg/services/ngalert/provisioning/compat.go index 13d0bba88a9..a4b3ea50922 100644 --- a/pkg/services/ngalert/provisioning/compat.go +++ b/pkg/services/ngalert/provisioning/compat.go @@ -3,19 +3,19 @@ package provisioning import ( "strings" - alertingNotify "github.com/grafana/alerting/notify" + alertingModels "github.com/grafana/alerting/models" "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" "github.com/grafana/grafana/pkg/services/ngalert/models" ) -func EmbeddedContactPointToGrafanaIntegrationConfig(e definitions.EmbeddedContactPoint) (alertingNotify.GrafanaIntegrationConfig, error) { +func EmbeddedContactPointToGrafanaIntegrationConfig(e definitions.EmbeddedContactPoint) (alertingModels.IntegrationConfig, error) { data, err := e.Settings.MarshalJSON() if err != nil { - return alertingNotify.GrafanaIntegrationConfig{}, err + return alertingModels.IntegrationConfig{}, err } - return alertingNotify.GrafanaIntegrationConfig{ + return alertingModels.IntegrationConfig{ UID: e.UID, Name: e.Name, Type: e.Type, diff --git a/pkg/services/ngalert/provisioning/contactpoints_test.go b/pkg/services/ngalert/provisioning/contactpoints_test.go index b85dfcd3108..1a281f912b6 100644 --- a/pkg/services/ngalert/provisioning/contactpoints_test.go +++ b/pkg/services/ngalert/provisioning/contactpoints_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/grafana/alerting/notify" + "github.com/grafana/alerting/notify/notifytest" "github.com/grafana/alerting/receivers/schema" "github.com/prometheus/alertmanager/config" "github.com/stretchr/testify/assert" @@ -425,7 +426,7 @@ func TestIntegrationContactPointServiceDecryptRedact(t *testing.T) { } func TestRemoveSecretsForContactPoint(t *testing.T) { - overrides := map[string]func(settings map[string]any){ + overrides := map[schema.IntegrationType]func(settings map[string]any){ "webhook": func(settings map[string]any) { // add additional field to the settings because valid config does not allow it to be specified along with password settings["authorization_credentials"] = "test-authz-creds" }, @@ -437,23 +438,23 @@ func TestRemoveSecretsForContactPoint(t *testing.T) { }, } - configs := notify.AllKnownConfigsForTesting + configs := notifytest.AllKnownV1ConfigsForTesting keys := maps.Keys(configs) slices.Sort(keys) for _, integrationType := range keys { - integration := models.IntegrationGen(models.IntegrationMuts.WithValidConfig(schema.IntegrationType(integrationType)))() + integration := models.IntegrationGen(models.IntegrationMuts.WithValidConfig(integrationType))() if f, ok := overrides[integrationType]; ok { f(integration.Settings) } settingsRaw, err := json.Marshal(integration.Settings) require.NoError(t, err) - typeSchema, _ := notify.GetSchemaVersionForIntegration(schema.IntegrationType(integrationType), schema.V1) + typeSchema, _ := notify.GetSchemaVersionForIntegration(integrationType, schema.V1) expectedFields := typeSchema.GetSecretFieldsPaths() - t.Run(integrationType, func(t *testing.T) { + t.Run(string(integrationType), func(t *testing.T) { cp := definitions.EmbeddedContactPoint{ - Name: "integration-" + integrationType, - Type: integrationType, + Name: "integration-" + string(integrationType), + Type: string(integrationType), Settings: simplejson.MustJson(settingsRaw), } secureFields, err := RemoveSecretsForContactPoint(&cp) diff --git a/pkg/services/ngalert/remote/alertmanager.go b/pkg/services/ngalert/remote/alertmanager.go index 7048810195f..8cde9ee198f 100644 --- a/pkg/services/ngalert/remote/alertmanager.go +++ b/pkg/services/ngalert/remote/alertmanager.go @@ -609,10 +609,7 @@ func (am *Alertmanager) TestReceivers(ctx context.Context, c apimodels.TestRecei return nil, 0, fmt.Errorf("failed to decrypt receivers: %w", err) } - apiReceivers := make([]*alertingNotify.APIReceiver, 0, len(c.Receivers)) - for _, r := range decryptedReceivers { - apiReceivers = append(apiReceivers, notifier.PostableApiReceiverToApiReceiver(r)) - } + apiReceivers := alertingNotify.PostableAPIReceiversToAPIReceivers(decryptedReceivers) var alert *alertingNotify.TestReceiversConfigAlertParams if c.Alert != nil { alert = &alertingNotify.TestReceiversConfigAlertParams{Annotations: c.Alert.Annotations, Labels: c.Alert.Labels} diff --git a/pkg/services/ngalert/remote/mock/remoteAlertmanager.go b/pkg/services/ngalert/remote/mock/remoteAlertmanager.go index 1199b65ae9c..8f8e506c765 100644 --- a/pkg/services/ngalert/remote/mock/remoteAlertmanager.go +++ b/pkg/services/ngalert/remote/mock/remoteAlertmanager.go @@ -358,23 +358,23 @@ func (_c *RemoteAlertmanagerMock_GetAlerts_Call) RunAndReturn(run func(context.C } // GetReceivers provides a mock function with given fields: ctx -func (_m *RemoteAlertmanagerMock) GetReceivers(ctx context.Context) ([]alertingmodels.Receiver, error) { +func (_m *RemoteAlertmanagerMock) GetReceivers(ctx context.Context) ([]alertingmodels.ReceiverStatus, error) { ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for GetReceivers") } - var r0 []alertingmodels.Receiver + var r0 []alertingmodels.ReceiverStatus var r1 error - if rf, ok := ret.Get(0).(func(context.Context) ([]alertingmodels.Receiver, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context) ([]alertingmodels.ReceiverStatus, error)); ok { return rf(ctx) } - if rf, ok := ret.Get(0).(func(context.Context) []alertingmodels.Receiver); ok { + if rf, ok := ret.Get(0).(func(context.Context) []alertingmodels.ReceiverStatus); ok { r0 = rf(ctx) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]alertingmodels.Receiver) + r0 = ret.Get(0).([]alertingmodels.ReceiverStatus) } } @@ -405,12 +405,12 @@ func (_c *RemoteAlertmanagerMock_GetReceivers_Call) Run(run func(ctx context.Con return _c } -func (_c *RemoteAlertmanagerMock_GetReceivers_Call) Return(_a0 []alertingmodels.Receiver, _a1 error) *RemoteAlertmanagerMock_GetReceivers_Call { +func (_c *RemoteAlertmanagerMock_GetReceivers_Call) Return(_a0 []alertingmodels.ReceiverStatus, _a1 error) *RemoteAlertmanagerMock_GetReceivers_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *RemoteAlertmanagerMock_GetReceivers_Call) RunAndReturn(run func(context.Context) ([]alertingmodels.Receiver, error)) *RemoteAlertmanagerMock_GetReceivers_Call { +func (_c *RemoteAlertmanagerMock_GetReceivers_Call) RunAndReturn(run func(context.Context) ([]alertingmodels.ReceiverStatus, error)) *RemoteAlertmanagerMock_GetReceivers_Call { _c.Call.Return(run) return _c } diff --git a/pkg/tests/api/alerting/test-data/provisioning-mixed-set.yaml b/pkg/tests/api/alerting/test-data/provisioning-mixed-set.yaml index b8845d29548..41b63fc2ed6 100644 --- a/pkg/tests/api/alerting/test-data/provisioning-mixed-set.yaml +++ b/pkg/tests/api/alerting/test-data/provisioning-mixed-set.yaml @@ -144,16 +144,17 @@ policies: - label_keys_not_$$escaped # a list of prometheus-like matchers that an alert rule has to fulfill to match the node (allowed chars # [a-zA-Z_:]) - matchers: - - alertname = Watchdog - - service_id_X = serviceX - - severity =~ "warning|critical" - # a list of grafana-like matchers that an alert rule has to fulfill to match the node - object_matchers: - - ["alertname", "=", "CPUUsage"] - - ["service_id-X", "=", "serviceX"] - - ["severity", "=~", "warning|critical"] group_wait: 30s group_interval: 5m repeat_interval: 4h - routes: [] + routes: + - matchers: + - alertname = Watchdog + - service_id_X = serviceX + - severity =~ "warning|critical" + # a list of grafana-like matchers that an alert rule has to fulfill to match the node + object_matchers: + - [ "alertname", "=", "CPUUsage" ] + - [ "service_id-X", "=", "serviceX" ] + - [ "severity", "=~", "warning|critical" ] + diff --git a/pkg/tests/apis/alerting/notifications/receivers/receiver_test.go b/pkg/tests/apis/alerting/notifications/receivers/receiver_test.go index 1d34b5106c8..da834b690e8 100644 --- a/pkg/tests/apis/alerting/notifications/receivers/receiver_test.go +++ b/pkg/tests/apis/alerting/notifications/receivers/receiver_test.go @@ -9,10 +9,11 @@ import ( "net/http" "path" "slices" - "sort" "strings" "testing" + "github.com/grafana/alerting/notify/notifytest" + "github.com/grafana/alerting/receivers/line" "github.com/grafana/alerting/receivers/schema" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -1225,7 +1226,7 @@ func TestIntegrationCRUD(t *testing.T) { t.Run("should be able to update default receiver", func(t *testing.T) { require.NotNil(t, defaultReceiver) newDefault := defaultReceiver.Copy().(*v0alpha1.Receiver) - newDefault.Spec.Integrations = append(newDefault.Spec.Integrations, createIntegration(t, "line")) + newDefault.Spec.Integrations = append(newDefault.Spec.Integrations, createIntegration(t, line.Type)) updatedReceiver, err := adminClient.Update(ctx, newDefault, v1.UpdateOptions{}) require.NoError(t, err) @@ -1266,10 +1267,10 @@ func TestIntegrationCRUD(t *testing.T) { var receiver *v0alpha1.Receiver t.Run("should correctly persist all known integrations", func(t *testing.T) { - integrations := make([]v0alpha1.ReceiverIntegration, 0, len(notify.AllKnownConfigsForTesting)) - keysIter := maps.Keys(notify.AllKnownConfigsForTesting) + integrations := make([]v0alpha1.ReceiverIntegration, 0, len(notifytest.AllKnownV1ConfigsForTesting)) + keysIter := maps.Keys(notifytest.AllKnownV1ConfigsForTesting) keys := slices.Collect(keysIter) - sort.Strings(keys) + slices.Sort(keys) for _, key := range keys { integrations = append(integrations, createIntegration(t, key)) } @@ -1300,7 +1301,7 @@ func TestIntegrationCRUD(t *testing.T) { export := legacyCli.ExportReceiverTyped(t, receiver.Spec.Title, true) for _, integration := range export.Receivers { - expected := notify.AllKnownConfigsForTesting[strings.ToLower(integration.Type)] // to lower because there is LINE that is in different casing in API + expected := notifytest.AllKnownV1ConfigsForTesting[schema.IntegrationType(integration.Type)] assert.JSONEqf(t, expected.Config, string(integration.Settings), "integration %s", integration.Type) } }) @@ -1313,7 +1314,7 @@ func TestIntegrationCRUD(t *testing.T) { for _, integration := range get.Spec.Integrations { integrationType := schema.IntegrationType(integration.Type) t.Run(integration.Type, func(t *testing.T) { - expected := notify.AllKnownConfigsForTesting[strings.ToLower(integration.Type)] + expected := notifytest.AllKnownV1ConfigsForTesting[schema.IntegrationType(integration.Type)] var fields map[string]any require.NoError(t, json.Unmarshal([]byte(expected.Config), &fields)) typeSchema, ok := notify.GetSchemaVersionForIntegration(integrationType, schema.V1) @@ -1336,11 +1337,11 @@ func TestIntegrationCRUD(t *testing.T) { }) t.Run("should fail to persist receiver with invalid config", func(t *testing.T) { - keysIter := maps.Keys(notify.AllKnownConfigsForTesting) + keysIter := maps.Keys(notifytest.AllKnownV1ConfigsForTesting) keys := slices.Collect(keysIter) - sort.Strings(keys) + slices.Sort(keys) for _, key := range keys { - t.Run(key, func(t *testing.T) { + t.Run(string(key), func(t *testing.T) { integration := createIntegration(t, key) // Make the integration invalid, so it fails to create. This is usually done by sending empty settings. clear(integration.Settings) @@ -1503,18 +1504,18 @@ func persistInitialConfig(t *testing.T, amConfig definitions.PostableUserConfig) require.NoError(t, err) } -func createIntegration(t *testing.T, integrationType string) v0alpha1.ReceiverIntegration { - cfg, ok := notify.AllKnownConfigsForTesting[integrationType] +func createIntegration(t *testing.T, integrationType schema.IntegrationType) v0alpha1.ReceiverIntegration { + cfg, ok := notifytest.AllKnownV1ConfigsForTesting[integrationType] require.Truef(t, ok, "no known config for integration type %s", integrationType) - return createIntegrationWithSettings(t, integrationType, "v1", cfg.Config) + return createIntegrationWithSettings(t, integrationType, schema.V1, cfg.Config) } -func createIntegrationWithSettings(t *testing.T, integrationType string, integrationVersion string, settingsJson string) v0alpha1.ReceiverIntegration { +func createIntegrationWithSettings(t *testing.T, integrationType schema.IntegrationType, integrationVersion schema.Version, settingsJson string) v0alpha1.ReceiverIntegration { settings := common.Unstructured{} require.NoError(t, settings.UnmarshalJSON([]byte(settingsJson))) return v0alpha1.ReceiverIntegration{ Settings: settings.Object, - Type: integrationType, - Version: integrationVersion, + Type: string(integrationType), + Version: string(integrationVersion), DisableResolveMessage: util.Pointer(false), } }