|
|
|
|
@@ -12,6 +12,7 @@ import (
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
"golang.org/x/exp/rand"
|
|
|
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
|
|
|
"github.com/grafana/grafana/pkg/services/folder"
|
|
|
|
|
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
|
|
|
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
|
|
|
|
@@ -42,6 +43,11 @@ func config(t *testing.T) *setting.UnifiedAlertingSettings {
|
|
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func makeLimits(cfg *setting.UnifiedAlertingSettings) RuleLimits {
|
|
|
|
|
baseToggles := featuremgmt.WithFeatures()
|
|
|
|
|
return RuleLimitsFromConfig(cfg, baseToggles)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func validRule() apimodels.PostableExtendedRuleNode {
|
|
|
|
|
forDuration := model.Duration(rand.Int63n(1000))
|
|
|
|
|
uid := util.GenerateShortUID()
|
|
|
|
|
@@ -195,10 +201,11 @@ func TestValidateRuleGroup(t *testing.T) {
|
|
|
|
|
rules = append(rules, validRule())
|
|
|
|
|
}
|
|
|
|
|
cfg := config(t)
|
|
|
|
|
limits := makeLimits(cfg)
|
|
|
|
|
|
|
|
|
|
t.Run("should validate struct and rules", func(t *testing.T) {
|
|
|
|
|
g := validGroup(cfg, rules...)
|
|
|
|
|
alerts, err := ValidateRuleGroup(&g, orgId, folder.UID, RuleLimitsFromConfig(cfg))
|
|
|
|
|
alerts, err := ValidateRuleGroup(&g, orgId, folder.UID, limits)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Len(t, alerts, len(rules))
|
|
|
|
|
})
|
|
|
|
|
@@ -206,7 +213,7 @@ func TestValidateRuleGroup(t *testing.T) {
|
|
|
|
|
t.Run("should default to default interval from config if group interval is 0", func(t *testing.T) {
|
|
|
|
|
g := validGroup(cfg, rules...)
|
|
|
|
|
g.Interval = 0
|
|
|
|
|
alerts, err := ValidateRuleGroup(&g, orgId, folder.UID, RuleLimitsFromConfig(cfg))
|
|
|
|
|
alerts, err := ValidateRuleGroup(&g, orgId, folder.UID, limits)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
for _, alert := range alerts {
|
|
|
|
|
require.Equal(t, int64(cfg.DefaultRuleEvaluationInterval.Seconds()), alert.IntervalSeconds)
|
|
|
|
|
@@ -221,7 +228,7 @@ func TestValidateRuleGroup(t *testing.T) {
|
|
|
|
|
isPaused = !(isPaused)
|
|
|
|
|
}
|
|
|
|
|
g := validGroup(cfg, rules...)
|
|
|
|
|
alerts, err := ValidateRuleGroup(&g, orgId, folder.UID, RuleLimitsFromConfig(cfg))
|
|
|
|
|
alerts, err := ValidateRuleGroup(&g, orgId, folder.UID, limits)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
for _, alert := range alerts {
|
|
|
|
|
require.True(t, alert.HasPause)
|
|
|
|
|
@@ -233,6 +240,7 @@ func TestValidateRuleGroupFailures(t *testing.T) {
|
|
|
|
|
orgId := rand.Int63()
|
|
|
|
|
folder := randFolder()
|
|
|
|
|
cfg := config(t)
|
|
|
|
|
limits := makeLimits(cfg)
|
|
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
|
name string
|
|
|
|
|
@@ -293,7 +301,7 @@ func TestValidateRuleGroupFailures(t *testing.T) {
|
|
|
|
|
for _, testCase := range testCases {
|
|
|
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
|
|
|
g := testCase.group()
|
|
|
|
|
_, err := ValidateRuleGroup(g, orgId, folder.UID, RuleLimitsFromConfig(cfg))
|
|
|
|
|
_, err := ValidateRuleGroup(g, orgId, folder.UID, limits)
|
|
|
|
|
require.Error(t, err)
|
|
|
|
|
if testCase.assert != nil {
|
|
|
|
|
testCase.assert(t, g, err)
|
|
|
|
|
@@ -307,6 +315,7 @@ func TestValidateRuleNode_NoUID(t *testing.T) {
|
|
|
|
|
folder := randFolder()
|
|
|
|
|
name := util.GenerateShortUID()
|
|
|
|
|
var cfg = config(t)
|
|
|
|
|
limits := makeLimits(cfg)
|
|
|
|
|
interval := cfg.BaseInterval * time.Duration(rand.Int63n(10)+1)
|
|
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
|
@@ -401,7 +410,7 @@ func TestValidateRuleNode_NoUID(t *testing.T) {
|
|
|
|
|
r := testCase.rule()
|
|
|
|
|
r.GrafanaManagedAlert.UID = ""
|
|
|
|
|
|
|
|
|
|
alert, err := validateRuleNode(r, name, interval, orgId, folder.UID, RuleLimitsFromConfig(cfg))
|
|
|
|
|
alert, err := validateRuleNode(r, name, interval, orgId, folder.UID, limits)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
testCase.assert(t, r, alert)
|
|
|
|
|
})
|
|
|
|
|
@@ -409,7 +418,7 @@ func TestValidateRuleNode_NoUID(t *testing.T) {
|
|
|
|
|
|
|
|
|
|
t.Run("accepts empty group name", func(t *testing.T) {
|
|
|
|
|
r := validRule()
|
|
|
|
|
alert, err := validateRuleNode(&r, "", interval, orgId, folder.UID, RuleLimitsFromConfig(cfg))
|
|
|
|
|
alert, err := validateRuleNode(&r, "", interval, orgId, folder.UID, limits)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, "", alert.RuleGroup)
|
|
|
|
|
})
|
|
|
|
|
@@ -419,6 +428,7 @@ func TestValidateRuleNodeFailures_NoUID(t *testing.T) {
|
|
|
|
|
orgId := rand.Int63()
|
|
|
|
|
folder := randFolder()
|
|
|
|
|
cfg := config(t)
|
|
|
|
|
limits := makeLimits(cfg)
|
|
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
|
name string
|
|
|
|
|
@@ -562,7 +572,7 @@ func TestValidateRuleNodeFailures_NoUID(t *testing.T) {
|
|
|
|
|
interval = *testCase.interval
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err := validateRuleNode(r, "", interval, orgId, folder.UID, RuleLimitsFromConfig(cfg))
|
|
|
|
|
_, err := validateRuleNode(r, "", interval, orgId, folder.UID, limits)
|
|
|
|
|
require.Error(t, err)
|
|
|
|
|
if testCase.assert != nil {
|
|
|
|
|
testCase.assert(t, r, err)
|
|
|
|
|
@@ -576,6 +586,7 @@ func TestValidateRuleNode_UID(t *testing.T) {
|
|
|
|
|
folder := randFolder()
|
|
|
|
|
name := util.GenerateShortUID()
|
|
|
|
|
var cfg = config(t)
|
|
|
|
|
limits := makeLimits(cfg)
|
|
|
|
|
interval := cfg.BaseInterval * time.Duration(rand.Int63n(10)+1)
|
|
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
|
@@ -654,7 +665,7 @@ func TestValidateRuleNode_UID(t *testing.T) {
|
|
|
|
|
for _, testCase := range testCases {
|
|
|
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
|
|
|
r := testCase.rule()
|
|
|
|
|
alert, err := validateRuleNode(r, name, interval, orgId, folder.UID, RuleLimitsFromConfig(cfg))
|
|
|
|
|
alert, err := validateRuleNode(r, name, interval, orgId, folder.UID, limits)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
testCase.assert(t, r, alert)
|
|
|
|
|
})
|
|
|
|
|
@@ -662,7 +673,7 @@ func TestValidateRuleNode_UID(t *testing.T) {
|
|
|
|
|
|
|
|
|
|
t.Run("accepts empty group name", func(t *testing.T) {
|
|
|
|
|
r := validRule()
|
|
|
|
|
alert, err := validateRuleNode(&r, "", interval, orgId, folder.UID, RuleLimitsFromConfig(cfg))
|
|
|
|
|
alert, err := validateRuleNode(&r, "", interval, orgId, folder.UID, limits)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, "", alert.RuleGroup)
|
|
|
|
|
})
|
|
|
|
|
@@ -672,6 +683,7 @@ func TestValidateRuleNodeFailures_UID(t *testing.T) {
|
|
|
|
|
orgId := rand.Int63()
|
|
|
|
|
folder := randFolder()
|
|
|
|
|
cfg := config(t)
|
|
|
|
|
limits := makeLimits(cfg)
|
|
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
|
name string
|
|
|
|
|
@@ -757,7 +769,7 @@ func TestValidateRuleNodeFailures_UID(t *testing.T) {
|
|
|
|
|
interval = *testCase.interval
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err := validateRuleNode(r, "", interval, orgId, folder.UID, RuleLimitsFromConfig(cfg))
|
|
|
|
|
_, err := validateRuleNode(r, "", interval, orgId, folder.UID, limits)
|
|
|
|
|
require.Error(t, err)
|
|
|
|
|
if testCase.assert != nil {
|
|
|
|
|
testCase.assert(t, r, err)
|
|
|
|
|
@@ -768,6 +780,7 @@ func TestValidateRuleNodeFailures_UID(t *testing.T) {
|
|
|
|
|
|
|
|
|
|
func TestValidateRuleNodeIntervalFailures(t *testing.T) {
|
|
|
|
|
cfg := config(t)
|
|
|
|
|
limits := makeLimits(cfg)
|
|
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
|
name string
|
|
|
|
|
@@ -790,7 +803,7 @@ func TestValidateRuleNodeIntervalFailures(t *testing.T) {
|
|
|
|
|
for _, testCase := range testCases {
|
|
|
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
|
|
|
r := validRule()
|
|
|
|
|
_, err := validateRuleNode(&r, util.GenerateShortUID(), testCase.interval, rand.Int63(), randFolder().UID, RuleLimitsFromConfig(cfg))
|
|
|
|
|
_, err := validateRuleNode(&r, util.GenerateShortUID(), testCase.interval, rand.Int63(), randFolder().UID, limits)
|
|
|
|
|
require.Error(t, err)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
@@ -798,6 +811,7 @@ func TestValidateRuleNodeIntervalFailures(t *testing.T) {
|
|
|
|
|
|
|
|
|
|
func TestValidateRuleNodeNotificationSettings(t *testing.T) {
|
|
|
|
|
cfg := config(t)
|
|
|
|
|
limits := makeLimits(cfg)
|
|
|
|
|
|
|
|
|
|
validNotificationSettings := models.NotificationSettingsGen(models.NSMuts.WithGroupBy(model.AlertNameLabel, models.FolderTitleLabel))
|
|
|
|
|
|
|
|
|
|
@@ -880,7 +894,7 @@ func TestValidateRuleNodeNotificationSettings(t *testing.T) {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
r := validRule()
|
|
|
|
|
r.GrafanaManagedAlert.NotificationSettings = AlertRuleNotificationSettingsFromNotificationSettings([]models.NotificationSettings{tt.notificationSettings})
|
|
|
|
|
_, err := validateRuleNode(&r, util.GenerateShortUID(), cfg.BaseInterval*time.Duration(rand.Int63n(10)+1), rand.Int63(), randFolder().UID, RuleLimitsFromConfig(cfg))
|
|
|
|
|
_, err := validateRuleNode(&r, util.GenerateShortUID(), cfg.BaseInterval*time.Duration(rand.Int63n(10)+1), rand.Int63(), randFolder().UID, limits)
|
|
|
|
|
|
|
|
|
|
if tt.expErrorContains != "" {
|
|
|
|
|
require.Error(t, err)
|
|
|
|
|
@@ -894,6 +908,7 @@ func TestValidateRuleNodeNotificationSettings(t *testing.T) {
|
|
|
|
|
|
|
|
|
|
func TestValidateRuleNodeReservedLabels(t *testing.T) {
|
|
|
|
|
cfg := config(t)
|
|
|
|
|
limits := makeLimits(cfg)
|
|
|
|
|
|
|
|
|
|
for label := range models.LabelsUserCannotSpecify {
|
|
|
|
|
t.Run(label, func(t *testing.T) {
|
|
|
|
|
@@ -901,7 +916,7 @@ func TestValidateRuleNodeReservedLabels(t *testing.T) {
|
|
|
|
|
r.ApiRuleNode.Labels = map[string]string{
|
|
|
|
|
label: "true",
|
|
|
|
|
}
|
|
|
|
|
_, err := validateRuleNode(&r, util.GenerateShortUID(), cfg.BaseInterval*time.Duration(rand.Int63n(10)+1), rand.Int63(), randFolder().UID, RuleLimitsFromConfig(cfg))
|
|
|
|
|
_, err := validateRuleNode(&r, util.GenerateShortUID(), cfg.BaseInterval*time.Duration(rand.Int63n(10)+1), rand.Int63(), randFolder().UID, limits)
|
|
|
|
|
require.Error(t, err)
|
|
|
|
|
require.ErrorContains(t, err, label)
|
|
|
|
|
})
|
|
|
|
|
|