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
This commit is contained in:
Yuri Tseretyan
2025-10-03 10:37:49 -04:00
committed by GitHub
parent cca9e0d55f
commit d0f79ee60d
25 changed files with 139 additions and 297 deletions
@@ -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)
@@ -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 := &notify.GrafanaIntegrationConfig{
e := &alertingModels.IntegrationConfig{
Type: integrationType,
Settings: data,
}
@@ -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 := &notify.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) {
@@ -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 {
+5 -4
View File
@@ -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 {
+9 -12
View File
@@ -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))()
+12 -4
View File
@@ -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{}
@@ -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
}
@@ -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
}
-36
View File
@@ -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 {
@@ -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])
}
@@ -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),
},
},
},
@@ -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 {
@@ -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
}
@@ -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",
}
+4 -4
View File
@@ -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,
@@ -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)
+1 -4
View File
@@ -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}
@@ -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
}