mirror of
https://github.com/grafana/grafana.git
synced 2025-01-27 16:57:14 -06:00
Alerting: Improve legacy migration to include send reminder & frequency (#60275)
* Alerting: Improve legacy migration to include send reminder & frequency Legacy channel frequency is migrated to the channel's migrated route's repeat interval if send reminder is true. If send reminder is false, we pseudo-disable the repeat interval by setting it to a large value (1y). If there were no default channels, the root notification policy is still created with the default 4h repeat interval.
This commit is contained in:
parent
be1c5e13d5
commit
63ba3ccb58
@ -8,6 +8,7 @@ import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/alertmanager/pkg/labels"
|
||||
"github.com/prometheus/common/model"
|
||||
@ -16,6 +17,11 @@ import (
|
||||
ngModels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
)
|
||||
|
||||
const (
|
||||
// DisabledRepeatInterval is a large duration that will be used as a pseudo-disable in case a legacy channel doesn't have SendReminders enabled.
|
||||
DisabledRepeatInterval = model.Duration(time.Duration(8736) * time.Hour) // 1y
|
||||
)
|
||||
|
||||
type notificationChannel struct {
|
||||
ID int64 `xorm:"id"`
|
||||
OrgID int64 `xorm:"org_id"`
|
||||
@ -26,6 +32,8 @@ type notificationChannel struct {
|
||||
IsDefault bool `xorm:"is_default"`
|
||||
Settings *simplejson.Json `xorm:"settings"`
|
||||
SecureSettings SecureJsonData `xorm:"secure_settings"`
|
||||
SendReminder bool `xorm:"send_reminder"`
|
||||
Frequency model.Duration `xorm:"frequency"`
|
||||
}
|
||||
|
||||
// channelsPerOrg maps notification channels per organisation
|
||||
@ -37,6 +45,12 @@ type defaultChannelsPerOrg map[int64][]*notificationChannel
|
||||
// uidOrID for both uid and ID, primarily used for mapping legacy channel to migrated receiver.
|
||||
type uidOrID interface{}
|
||||
|
||||
// channelReceiver is a convenience struct that contains a notificationChannel and its corresponding migrated PostableApiReceiver.
|
||||
type channelReceiver struct {
|
||||
channel *notificationChannel
|
||||
receiver *PostableApiReceiver
|
||||
}
|
||||
|
||||
// setupAlertmanagerConfigs creates Alertmanager configs with migrated receivers and routes.
|
||||
func (m *migration) setupAlertmanagerConfigs(rulesPerOrg map[int64]map[*alertRule][]uidOrID) (amConfigsPerOrg, error) {
|
||||
// allChannels: channelUID -> channelConfig
|
||||
@ -66,7 +80,9 @@ func (m *migration) setupAlertmanagerConfigs(rulesPerOrg map[int64]map[*alertRul
|
||||
continue
|
||||
}
|
||||
|
||||
amConfig.AlertmanagerConfig.Receivers = receivers
|
||||
for _, cr := range receivers {
|
||||
amConfig.AlertmanagerConfig.Receivers = append(amConfig.AlertmanagerConfig.Receivers, cr.receiver)
|
||||
}
|
||||
|
||||
defaultReceivers := make(map[string]struct{})
|
||||
defaultChannels, ok := defaultChannelsPerOrg[orgID]
|
||||
@ -85,10 +101,10 @@ func (m *migration) setupAlertmanagerConfigs(rulesPerOrg map[int64]map[*alertRul
|
||||
amConfig.AlertmanagerConfig.Receivers = append(amConfig.AlertmanagerConfig.Receivers, defaultReceiver)
|
||||
}
|
||||
|
||||
for _, recv := range receivers {
|
||||
route, err := createRoute(recv)
|
||||
for _, cr := range receivers {
|
||||
route, err := createRoute(cr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create route for receiver %s in orgId %d: %w", recv.Name, orgID, err)
|
||||
return nil, fmt.Errorf("failed to create route for receiver %s in orgId %d: %w", cr.receiver.Name, orgID, err)
|
||||
}
|
||||
|
||||
amConfigPerOrg[orgID].AlertmanagerConfig.Route.Routes = append(amConfigPerOrg[orgID].AlertmanagerConfig.Route.Routes, route)
|
||||
@ -141,7 +157,9 @@ func (m *migration) getNotificationChannelMap() (channelsPerOrg, defaultChannels
|
||||
disable_resolve_message,
|
||||
is_default,
|
||||
settings,
|
||||
secure_settings
|
||||
secure_settings,
|
||||
send_reminder,
|
||||
frequency
|
||||
FROM
|
||||
alert_notification
|
||||
`
|
||||
@ -196,8 +214,8 @@ func (m *migration) createNotifier(c *notificationChannel) (*PostableGrafanaRece
|
||||
}
|
||||
|
||||
// Create one receiver for every unique notification channel.
|
||||
func (m *migration) createReceivers(allChannels []*notificationChannel) (map[uidOrID]*PostableApiReceiver, []*PostableApiReceiver, error) {
|
||||
receivers := make([]*PostableApiReceiver, 0, len(allChannels))
|
||||
func (m *migration) createReceivers(allChannels []*notificationChannel) (map[uidOrID]*PostableApiReceiver, []channelReceiver, error) {
|
||||
receivers := make([]channelReceiver, 0, len(allChannels))
|
||||
receiversMap := make(map[uidOrID]*PostableApiReceiver)
|
||||
|
||||
set := make(map[string]struct{}) // Used to deduplicate sanitized names.
|
||||
@ -218,20 +236,23 @@ func (m *migration) createReceivers(allChannels []*notificationChannel) (map[uid
|
||||
|
||||
set[sanitizedName] = struct{}{}
|
||||
|
||||
recv := &PostableApiReceiver{
|
||||
Name: sanitizedName, // Channel name is unique within an Org.
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{notifier},
|
||||
cr := channelReceiver{
|
||||
channel: c,
|
||||
receiver: &PostableApiReceiver{
|
||||
Name: sanitizedName, // Channel name is unique within an Org.
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{notifier},
|
||||
},
|
||||
}
|
||||
|
||||
receivers = append(receivers, recv)
|
||||
receivers = append(receivers, cr)
|
||||
|
||||
// Store receivers for creating routes from alert rules later.
|
||||
if c.Uid != "" {
|
||||
receiversMap[c.Uid] = recv
|
||||
receiversMap[c.Uid] = cr.receiver
|
||||
}
|
||||
if c.ID != 0 {
|
||||
// In certain circumstances, the alert rule uses ID instead of uid. So, we add this to be able to lookup by ID in case.
|
||||
receiversMap[c.ID] = recv
|
||||
receiversMap[c.ID] = cr.receiver
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,17 +261,27 @@ func (m *migration) createReceivers(allChannels []*notificationChannel) (map[uid
|
||||
|
||||
// Create the root-level route with the default receiver. If no new receiver is created specifically for the root-level route, the returned receiver will be nil.
|
||||
func (m *migration) createDefaultRouteAndReceiver(defaultChannels []*notificationChannel) (*PostableApiReceiver, *Route, error) {
|
||||
var defaultReceiver *PostableApiReceiver
|
||||
|
||||
defaultReceiverName := "autogen-contact-point-default"
|
||||
if len(defaultChannels) != 1 {
|
||||
// If there are zero or more than one default channels we create a separate contact group that is used only in the root policy. This is to simplify the migrated notification policy structure.
|
||||
// If we ever allow more than one receiver per route this won't be necessary.
|
||||
defaultReceiver = &PostableApiReceiver{
|
||||
Name: defaultReceiverName,
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{},
|
||||
}
|
||||
defaultRoute := &Route{
|
||||
Receiver: defaultReceiverName,
|
||||
Routes: make([]*Route, 0),
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, // To keep parity with pre-migration notifications.
|
||||
RepeatInterval: nil,
|
||||
}
|
||||
newDefaultReceiver := &PostableApiReceiver{
|
||||
Name: defaultReceiverName,
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{},
|
||||
}
|
||||
|
||||
// Return early if there are no default channels
|
||||
if len(defaultChannels) == 0 {
|
||||
return newDefaultReceiver, defaultRoute, nil
|
||||
}
|
||||
|
||||
repeatInterval := DisabledRepeatInterval // If no channels have SendReminders enabled, we will use this large value as a pseudo-disable.
|
||||
if len(defaultChannels) > 1 {
|
||||
// If there are more than one default channels we create a separate contact group that is used only in the root policy. This is to simplify the migrated notification policy structure.
|
||||
// If we ever allow more than one receiver per route this won't be necessary.
|
||||
for _, c := range defaultChannels {
|
||||
// Need to create a new notifier to prevent uid conflict.
|
||||
defaultNotifier, err := m.createNotifier(c)
|
||||
@ -258,39 +289,51 @@ func (m *migration) createDefaultRouteAndReceiver(defaultChannels []*notificatio
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
defaultReceiver.GrafanaManagedReceivers = append(defaultReceiver.GrafanaManagedReceivers, defaultNotifier)
|
||||
newDefaultReceiver.GrafanaManagedReceivers = append(newDefaultReceiver.GrafanaManagedReceivers, defaultNotifier)
|
||||
|
||||
// Choose the lowest send reminder duration from all the notifiers to use for default route.
|
||||
if c.SendReminder && c.Frequency < repeatInterval {
|
||||
repeatInterval = c.Frequency
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If there is only a single default channel, we don't need a separate receiver to hold it. We can reuse the existing receiver for that single notifier.
|
||||
defaultReceiverName = defaultChannels[0].Name
|
||||
}
|
||||
defaultRoute.Receiver = defaultChannels[0].Name
|
||||
if defaultChannels[0].SendReminder {
|
||||
repeatInterval = defaultChannels[0].Frequency
|
||||
}
|
||||
|
||||
defaultRoute := &Route{
|
||||
Receiver: defaultReceiverName,
|
||||
Routes: make([]*Route, 0),
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, // To keep parity with pre-migration notifications.
|
||||
// No need to create a new receiver.
|
||||
newDefaultReceiver = nil
|
||||
}
|
||||
defaultRoute.RepeatInterval = &repeatInterval
|
||||
|
||||
return defaultReceiver, defaultRoute, nil
|
||||
return newDefaultReceiver, defaultRoute, nil
|
||||
}
|
||||
|
||||
// Create one route per contact point, matching based on ContactLabel.
|
||||
func createRoute(recv *PostableApiReceiver) (*Route, error) {
|
||||
func createRoute(cr channelReceiver) (*Route, error) {
|
||||
// We create a regex matcher so that each alert rule need only have a single ContactLabel entry for all contact points it sends to.
|
||||
// For example, if an alert needs to send to contact1 and contact2 it will have ContactLabel=`"contact1","contact2"` and will match both routes looking
|
||||
// for `.*"contact1".*` and `.*"contact2".*`.
|
||||
|
||||
// We quote and escape here to ensure the regex will correctly match the ContactLabel on the alerts.
|
||||
name := fmt.Sprintf(`.*%s.*`, regexp.QuoteMeta(quote(recv.Name)))
|
||||
name := fmt.Sprintf(`.*%s.*`, regexp.QuoteMeta(quote(cr.receiver.Name)))
|
||||
mat, err := labels.NewMatcher(labels.MatchRegexp, ContactLabel, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repeatInterval := DisabledRepeatInterval
|
||||
if cr.channel.SendReminder {
|
||||
repeatInterval = cr.channel.Frequency
|
||||
}
|
||||
|
||||
return &Route{
|
||||
Receiver: recv.Name,
|
||||
Receiver: cr.receiver.Name,
|
||||
ObjectMatchers: ObjectMatchers{mat},
|
||||
Continue: true, // We continue so that each sibling contact point route can separately match.
|
||||
RepeatInterval: &repeatInterval,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -430,11 +473,12 @@ type PostableApiAlertingConfig struct {
|
||||
}
|
||||
|
||||
type Route struct {
|
||||
Receiver string `yaml:"receiver,omitempty" json:"receiver,omitempty"`
|
||||
ObjectMatchers ObjectMatchers `yaml:"object_matchers,omitempty" json:"object_matchers,omitempty"`
|
||||
Routes []*Route `yaml:"routes,omitempty" json:"routes,omitempty"`
|
||||
Continue bool `yaml:"continue,omitempty" json:"continue,omitempty"`
|
||||
GroupByStr []string `yaml:"group_by,omitempty" json:"group_by,omitempty"`
|
||||
Receiver string `yaml:"receiver,omitempty" json:"receiver,omitempty"`
|
||||
ObjectMatchers ObjectMatchers `yaml:"object_matchers,omitempty" json:"object_matchers,omitempty"`
|
||||
Routes []*Route `yaml:"routes,omitempty" json:"routes,omitempty"`
|
||||
Continue bool `yaml:"continue,omitempty" json:"continue,omitempty"`
|
||||
GroupByStr []string `yaml:"group_by,omitempty" json:"group_by,omitempty"`
|
||||
RepeatInterval *model.Duration `yaml:"repeat_interval,omitempty" json:"repeat_interval,omitempty"`
|
||||
}
|
||||
|
||||
type ObjectMatchers labels.Matchers
|
||||
|
@ -2,6 +2,7 @@ package ualert
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
@ -121,11 +122,13 @@ func TestFilterReceiversForAlert(t *testing.T) {
|
||||
func TestCreateRoute(t *testing.T) {
|
||||
tc := []struct {
|
||||
name string
|
||||
channel *notificationChannel
|
||||
recv *PostableApiReceiver
|
||||
expected *Route
|
||||
}{
|
||||
{
|
||||
name: "when a receiver is passed in, the route should regex match based on quoted name with continue=true",
|
||||
name: "when a receiver is passed in, the route should regex match based on quoted name with continue=true",
|
||||
channel: ¬ificationChannel{},
|
||||
recv: &PostableApiReceiver{
|
||||
Name: "recv1",
|
||||
},
|
||||
@ -135,10 +138,12 @@ func TestCreateRoute(t *testing.T) {
|
||||
Routes: nil,
|
||||
Continue: true,
|
||||
GroupByStr: nil,
|
||||
RepeatInterval: durationPointer(DisabledRepeatInterval),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "notification channel should be escaped for regex in the matcher",
|
||||
name: "notification channel should be escaped for regex in the matcher",
|
||||
channel: ¬ificationChannel{},
|
||||
recv: &PostableApiReceiver{
|
||||
Name: `. ^ $ * + - ? ( ) [ ] { } \ |`,
|
||||
},
|
||||
@ -148,13 +153,47 @@ func TestCreateRoute(t *testing.T) {
|
||||
Routes: nil,
|
||||
Continue: true,
|
||||
GroupByStr: nil,
|
||||
RepeatInterval: durationPointer(DisabledRepeatInterval),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "when a channel has sendReminder=true, the route should use the frequency in repeat interval",
|
||||
channel: ¬ificationChannel{SendReminder: true, Frequency: model.Duration(time.Duration(42) * time.Hour)},
|
||||
recv: &PostableApiReceiver{
|
||||
Name: "recv1",
|
||||
},
|
||||
expected: &Route{
|
||||
Receiver: "recv1",
|
||||
ObjectMatchers: ObjectMatchers{{Type: 2, Name: ContactLabel, Value: `.*"recv1".*`}},
|
||||
Routes: nil,
|
||||
Continue: true,
|
||||
GroupByStr: nil,
|
||||
RepeatInterval: durationPointer(model.Duration(time.Duration(42) * time.Hour)),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "when a channel has sendReminder=false, the route should ignore the frequency in repeat interval and use DisabledRepeatInterval",
|
||||
channel: ¬ificationChannel{SendReminder: false, Frequency: model.Duration(time.Duration(42) * time.Hour)},
|
||||
recv: &PostableApiReceiver{
|
||||
Name: "recv1",
|
||||
},
|
||||
expected: &Route{
|
||||
Receiver: "recv1",
|
||||
ObjectMatchers: ObjectMatchers{{Type: 2, Name: ContactLabel, Value: `.*"recv1".*`}},
|
||||
Routes: nil,
|
||||
Continue: true,
|
||||
GroupByStr: nil,
|
||||
RepeatInterval: durationPointer(DisabledRepeatInterval),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tc {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
res, err := createRoute(tt.recv)
|
||||
res, err := createRoute(channelReceiver{
|
||||
channel: tt.channel,
|
||||
receiver: tt.recv,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Order of nested routes is not guaranteed.
|
||||
@ -180,13 +219,18 @@ func createNotChannel(t *testing.T, uid string, id int64, name string) *notifica
|
||||
return ¬ificationChannel{Uid: uid, ID: id, Name: name, Settings: simplejson.New()}
|
||||
}
|
||||
|
||||
func createNotChannelWithReminder(t *testing.T, uid string, id int64, name string, frequency model.Duration) *notificationChannel {
|
||||
t.Helper()
|
||||
return ¬ificationChannel{Uid: uid, ID: id, Name: name, SendReminder: true, Frequency: frequency, Settings: simplejson.New()}
|
||||
}
|
||||
|
||||
func TestCreateReceivers(t *testing.T) {
|
||||
tc := []struct {
|
||||
name string
|
||||
allChannels []*notificationChannel
|
||||
defaultChannels []*notificationChannel
|
||||
expRecvMap map[uidOrID]*PostableApiReceiver
|
||||
expRecv []*PostableApiReceiver
|
||||
expRecv []channelReceiver
|
||||
expErr error
|
||||
}{
|
||||
{
|
||||
@ -210,14 +254,20 @@ func TestCreateReceivers(t *testing.T) {
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name2"}},
|
||||
},
|
||||
},
|
||||
expRecv: []*PostableApiReceiver{
|
||||
expRecv: []channelReceiver{
|
||||
{
|
||||
Name: "name1",
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name1"}},
|
||||
channel: createNotChannel(t, "uid1", int64(1), "name1"),
|
||||
receiver: &PostableApiReceiver{
|
||||
Name: "name1",
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name1"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "name2",
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name2"}},
|
||||
channel: createNotChannel(t, "uid2", int64(2), "name2"),
|
||||
receiver: &PostableApiReceiver{
|
||||
Name: "name2",
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name2"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -234,10 +284,13 @@ func TestCreateReceivers(t *testing.T) {
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name_1"}},
|
||||
},
|
||||
},
|
||||
expRecv: []*PostableApiReceiver{
|
||||
expRecv: []channelReceiver{
|
||||
{
|
||||
Name: "name_1",
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name_1"}},
|
||||
channel: createNotChannel(t, "uid1", int64(1), "name\"1"),
|
||||
receiver: &PostableApiReceiver{
|
||||
Name: "name_1",
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name_1"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -262,14 +315,20 @@ func TestCreateReceivers(t *testing.T) {
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name_1_dba13d"}},
|
||||
},
|
||||
},
|
||||
expRecv: []*PostableApiReceiver{
|
||||
expRecv: []channelReceiver{
|
||||
{
|
||||
Name: "name_1",
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name_1"}},
|
||||
channel: createNotChannel(t, "uid1", int64(1), "name\"1"),
|
||||
receiver: &PostableApiReceiver{
|
||||
Name: "name_1",
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name_1"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "name_1_dba13d",
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name_1_dba13d"}},
|
||||
channel: createNotChannel(t, "uid2", int64(2), "name_1"),
|
||||
receiver: &PostableApiReceiver{
|
||||
Name: "name_1_dba13d",
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name_1_dba13d"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -289,7 +348,7 @@ func TestCreateReceivers(t *testing.T) {
|
||||
|
||||
// We ignore certain fields for the purposes of this test
|
||||
for _, recv := range recvs {
|
||||
for _, not := range recv.GrafanaManagedReceivers {
|
||||
for _, not := range recv.receiver.GrafanaManagedReceivers {
|
||||
not.UID = ""
|
||||
not.Settings = nil
|
||||
not.SecureSettings = nil
|
||||
@ -319,9 +378,27 @@ func TestCreateDefaultRouteAndReceiver(t *testing.T) {
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name1"}, {Name: "name2"}},
|
||||
},
|
||||
expRoute: &Route{
|
||||
Receiver: "autogen-contact-point-default",
|
||||
Routes: make([]*Route, 0),
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Receiver: "autogen-contact-point-default",
|
||||
Routes: make([]*Route, 0),
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
RepeatInterval: durationPointer(DisabledRepeatInterval),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "when given multiple default notification channels migrate them to a single receiver with RepeatInterval set to be the minimum of all channel frequencies",
|
||||
defaultChannels: []*notificationChannel{
|
||||
createNotChannelWithReminder(t, "uid1", int64(1), "name1", model.Duration(42)),
|
||||
createNotChannelWithReminder(t, "uid2", int64(2), "name2", model.Duration(100000)),
|
||||
},
|
||||
expRecv: &PostableApiReceiver{
|
||||
Name: "autogen-contact-point-default",
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{{Name: "name1"}, {Name: "name2"}},
|
||||
},
|
||||
expRoute: &Route{
|
||||
Receiver: "autogen-contact-point-default",
|
||||
Routes: make([]*Route, 0),
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
RepeatInterval: durationPointer(model.Duration(42)),
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -332,9 +409,10 @@ func TestCreateDefaultRouteAndReceiver(t *testing.T) {
|
||||
GrafanaManagedReceivers: []*PostableGrafanaReceiver{},
|
||||
},
|
||||
expRoute: &Route{
|
||||
Receiver: "autogen-contact-point-default",
|
||||
Routes: make([]*Route, 0),
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Receiver: "autogen-contact-point-default",
|
||||
Routes: make([]*Route, 0),
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
RepeatInterval: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -342,9 +420,21 @@ func TestCreateDefaultRouteAndReceiver(t *testing.T) {
|
||||
defaultChannels: []*notificationChannel{createNotChannel(t, "uid1", int64(1), "name1")},
|
||||
expRecv: nil,
|
||||
expRoute: &Route{
|
||||
Receiver: "name1",
|
||||
Routes: make([]*Route, 0),
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Receiver: "name1",
|
||||
Routes: make([]*Route, 0),
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
RepeatInterval: durationPointer(DisabledRepeatInterval),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "when given a single default notification channel with SendReminder=true, use the channels Frequency as the RepeatInterval",
|
||||
defaultChannels: []*notificationChannel{createNotChannelWithReminder(t, "uid1", int64(1), "name1", model.Duration(42))},
|
||||
expRecv: nil,
|
||||
expRoute: &Route{
|
||||
Receiver: "name1",
|
||||
Routes: make([]*Route, 0),
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
RepeatInterval: durationPointer(model.Duration(42)),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -375,3 +465,7 @@ func TestCreateDefaultRouteAndReceiver(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func durationPointer(d model.Duration) *model.Duration {
|
||||
return &d
|
||||
}
|
||||
|
@ -158,10 +158,11 @@ func TestAMConfigMigration(t *testing.T) {
|
||||
Receiver: "autogen-contact-point-default",
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Routes: []*ualert.Route{
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier2", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier2".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier3", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier3".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
{Receiver: "notifier2", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier2".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
{Receiver: "notifier3", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier3".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
},
|
||||
RepeatInterval: nil,
|
||||
},
|
||||
Receivers: []*ualert.PostableApiReceiver{
|
||||
{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}},
|
||||
@ -177,15 +178,16 @@ func TestAMConfigMigration(t *testing.T) {
|
||||
Receiver: "notifier6",
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Routes: []*ualert.Route{
|
||||
{Receiver: "notifier4", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier4".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier5", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier5".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier6", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier6".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier4", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier4".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
{Receiver: "notifier5", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier5".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
{Receiver: "notifier6", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier6".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
},
|
||||
RepeatInterval: durationPointer(ualert.DisabledRepeatInterval),
|
||||
},
|
||||
Receivers: []*ualert.PostableApiReceiver{
|
||||
{Name: "notifier4", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier4", Type: "email"}}},
|
||||
{Name: "notifier5", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier5", Type: "slack"}}},
|
||||
{Name: "notifier6", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier6", Type: "opsgenie"}}}, // empty default
|
||||
{Name: "notifier6", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier6", Type: "opsgenie"}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -204,8 +206,9 @@ func TestAMConfigMigration(t *testing.T) {
|
||||
Receiver: "autogen-contact-point-default",
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Routes: []*ualert.Route{
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
},
|
||||
RepeatInterval: nil,
|
||||
},
|
||||
Receivers: []*ualert.PostableApiReceiver{
|
||||
{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}},
|
||||
@ -228,8 +231,33 @@ func TestAMConfigMigration(t *testing.T) {
|
||||
Receiver: "notifier1",
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Routes: []*ualert.Route{
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
},
|
||||
RepeatInterval: durationPointer(ualert.DisabledRepeatInterval),
|
||||
},
|
||||
Receivers: []*ualert.PostableApiReceiver{
|
||||
{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "when single default channel with SendReminder, use channel Frequency as RepeatInterval",
|
||||
legacyChannels: []*models.AlertNotification{
|
||||
createAlertNotificationWithReminder(t, int64(1), "notifier1", "email", emailSettings, true, true, time.Duration(1)*time.Hour),
|
||||
},
|
||||
alerts: []*models.Alert{},
|
||||
expected: map[int64]*ualert.PostableUserConfig{
|
||||
int64(1): {
|
||||
AlertmanagerConfig: ualert.PostableApiAlertingConfig{
|
||||
Route: &ualert.Route{
|
||||
Receiver: "notifier1",
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Routes: []*ualert.Route{
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(model.Duration(time.Duration(1) * time.Hour))},
|
||||
},
|
||||
RepeatInterval: durationPointer(model.Duration(time.Duration(1) * time.Hour)),
|
||||
},
|
||||
Receivers: []*ualert.PostableApiReceiver{
|
||||
{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}},
|
||||
@ -252,9 +280,38 @@ func TestAMConfigMigration(t *testing.T) {
|
||||
Receiver: "autogen-contact-point-default",
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Routes: []*ualert.Route{
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier2", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier2".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
{Receiver: "notifier2", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier2".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
},
|
||||
RepeatInterval: durationPointer(ualert.DisabledRepeatInterval),
|
||||
},
|
||||
Receivers: []*ualert.PostableApiReceiver{
|
||||
{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}},
|
||||
{Name: "notifier2", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier2", Type: "slack"}}},
|
||||
{Name: "autogen-contact-point-default", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}, {Name: "notifier2", Type: "slack"}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "when multiple default channels with SendReminder, use minimum channel frequency as RepeatInterval",
|
||||
legacyChannels: []*models.AlertNotification{
|
||||
createAlertNotificationWithReminder(t, int64(1), "notifier1", "email", emailSettings, true, true, time.Duration(1)*time.Hour),
|
||||
createAlertNotificationWithReminder(t, int64(1), "notifier2", "slack", slackSettings, true, true, time.Duration(30)*time.Minute),
|
||||
},
|
||||
alerts: []*models.Alert{},
|
||||
expected: map[int64]*ualert.PostableUserConfig{
|
||||
int64(1): {
|
||||
AlertmanagerConfig: ualert.PostableApiAlertingConfig{
|
||||
Route: &ualert.Route{
|
||||
Receiver: "autogen-contact-point-default",
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Routes: []*ualert.Route{
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(model.Duration(time.Duration(1) * time.Hour))},
|
||||
{Receiver: "notifier2", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier2".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(model.Duration(time.Duration(30) * time.Minute))},
|
||||
},
|
||||
RepeatInterval: durationPointer(model.Duration(time.Duration(30) * time.Minute)),
|
||||
},
|
||||
Receivers: []*ualert.PostableApiReceiver{
|
||||
{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}},
|
||||
@ -280,10 +337,11 @@ func TestAMConfigMigration(t *testing.T) {
|
||||
Receiver: "autogen-contact-point-default",
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Routes: []*ualert.Route{
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier2", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier2".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier3", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier3".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
{Receiver: "notifier2", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier2".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
{Receiver: "notifier3", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier3".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
},
|
||||
RepeatInterval: durationPointer(ualert.DisabledRepeatInterval),
|
||||
},
|
||||
Receivers: []*ualert.PostableApiReceiver{
|
||||
{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}},
|
||||
@ -294,36 +352,6 @@ func TestAMConfigMigration(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "when alert has only defaults, don't create route for it",
|
||||
legacyChannels: []*models.AlertNotification{
|
||||
createAlertNotification(t, int64(1), "notifier1", "email", emailSettings, true), // default
|
||||
createAlertNotification(t, int64(1), "notifier2", "slack", slackSettings, true), // default
|
||||
},
|
||||
alerts: []*models.Alert{
|
||||
createAlert(t, int64(1), int64(1), int64(1), "alert1", []string{"notifier1"}),
|
||||
createAlert(t, int64(1), int64(2), int64(3), "alert2", []string{}),
|
||||
},
|
||||
expected: map[int64]*ualert.PostableUserConfig{
|
||||
int64(1): {
|
||||
AlertmanagerConfig: ualert.PostableApiAlertingConfig{
|
||||
Route: &ualert.Route{
|
||||
Receiver: "autogen-contact-point-default",
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Routes: []*ualert.Route{
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier2", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier2".*`}}, Routes: nil, Continue: true},
|
||||
},
|
||||
},
|
||||
Receivers: []*ualert.PostableApiReceiver{
|
||||
{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}},
|
||||
{Name: "notifier2", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier2", Type: "slack"}}},
|
||||
{Name: "autogen-contact-point-default", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}, {Name: "notifier2", Type: "slack"}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "when alerts share channels, only create one receiver per legacy channel",
|
||||
legacyChannels: []*models.AlertNotification{
|
||||
@ -341,8 +369,8 @@ func TestAMConfigMigration(t *testing.T) {
|
||||
Receiver: "autogen-contact-point-default",
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Routes: []*ualert.Route{
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier2", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier2".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
{Receiver: "notifier2", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier2".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
},
|
||||
},
|
||||
Receivers: []*ualert.PostableApiReceiver{
|
||||
@ -367,7 +395,7 @@ func TestAMConfigMigration(t *testing.T) {
|
||||
Receiver: "autogen-contact-point-default",
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Routes: []*ualert.Route{
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
},
|
||||
},
|
||||
Receivers: []*ualert.PostableApiReceiver{
|
||||
@ -393,7 +421,7 @@ func TestAMConfigMigration(t *testing.T) {
|
||||
Receiver: "autogen-contact-point-default",
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Routes: []*ualert.Route{
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
},
|
||||
},
|
||||
Receivers: []*ualert.PostableApiReceiver{
|
||||
@ -420,7 +448,7 @@ func TestAMConfigMigration(t *testing.T) {
|
||||
Receiver: "autogen-contact-point-default",
|
||||
GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel},
|
||||
Routes: []*ualert.Route{
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true},
|
||||
{Receiver: "notifier1", ObjectMatchers: ualert.ObjectMatchers{{Type: 2, Name: ualert.ContactLabel, Value: `.*"notifier1".*`}}, Routes: nil, Continue: true, RepeatInterval: durationPointer(ualert.DisabledRepeatInterval)},
|
||||
},
|
||||
},
|
||||
Receivers: []*ualert.PostableApiReceiver{
|
||||
@ -444,6 +472,7 @@ func TestAMConfigMigration(t *testing.T) {
|
||||
|
||||
// Order of nested GrafanaManagedReceivers is not guaranteed.
|
||||
cOpt := []cmp.Option{
|
||||
cmpopts.IgnoreUnexported(ualert.PostableApiReceiver{}),
|
||||
cmpopts.IgnoreFields(ualert.PostableGrafanaReceiver{}, "UID", "Settings", "SecureSettings"),
|
||||
cmpopts.SortSlices(func(a, b *ualert.PostableGrafanaReceiver) bool { return a.Name < b.Name }),
|
||||
cmpopts.SortSlices(func(a, b *ualert.PostableApiReceiver) bool { return a.Name < b.Name }),
|
||||
@ -576,8 +605,8 @@ var (
|
||||
now = time.Now()
|
||||
)
|
||||
|
||||
// createAlertNotification creates a legacy alert notification channel for inserting into the test database.
|
||||
func createAlertNotification(t *testing.T, orgId int64, uid string, channelType string, settings string, defaultChannel bool) *models.AlertNotification {
|
||||
// createAlertNotificationWithReminder creates a legacy alert notification channel for inserting into the test database.
|
||||
func createAlertNotificationWithReminder(t *testing.T, orgId int64, uid string, channelType string, settings string, defaultChannel bool, sendReminder bool, frequency time.Duration) *models.AlertNotification {
|
||||
t.Helper()
|
||||
settingsJson := simplejson.New()
|
||||
if settings != "" {
|
||||
@ -599,9 +628,16 @@ func createAlertNotification(t *testing.T, orgId int64, uid string, channelType
|
||||
SecureSettings: make(map[string][]byte),
|
||||
Created: now,
|
||||
Updated: now,
|
||||
SendReminder: sendReminder,
|
||||
Frequency: frequency,
|
||||
}
|
||||
}
|
||||
|
||||
// createAlertNotification creates a legacy alert notification channel for inserting into the test database.
|
||||
func createAlertNotification(t *testing.T, orgId int64, uid string, channelType string, settings string, defaultChannel bool) *models.AlertNotification {
|
||||
return createAlertNotificationWithReminder(t, orgId, uid, channelType, settings, defaultChannel, false, time.Duration(0))
|
||||
}
|
||||
|
||||
// createAlert creates a legacy alert rule for inserting into the test database.
|
||||
func createAlert(t *testing.T, orgId int64, dashboardId int64, panelsId int64, name string, notifierUids []string) *models.Alert {
|
||||
t.Helper()
|
||||
@ -766,3 +802,7 @@ func getAlertRules(t *testing.T, x *xorm.Engine, orgId int64) []*ngModels.AlertR
|
||||
func boolPointer(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
|
||||
func durationPointer(d model.Duration) *model.Duration {
|
||||
return &d
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user