243 lines
8.7 KiB
Go
243 lines
8.7 KiB
Go
package store
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/log/logtest"
|
|
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
|
"github.com/grafana/grafana/pkg/util"
|
|
)
|
|
|
|
func TestAlertRuleToModelsAlertRule(t *testing.T) {
|
|
g := ngmodels.RuleGen
|
|
|
|
t.Run("make sure no data is lost between conversions", func(t *testing.T) {
|
|
for _, rule := range g.GenerateMany(100) {
|
|
r, err := alertRuleFromModelsAlertRule(rule)
|
|
require.NoError(t, err)
|
|
clone, err := alertRuleToModelsAlertRule(r, &logtest.Fake{})
|
|
require.NoError(t, err)
|
|
require.Empty(t, rule.Diff(&clone))
|
|
}
|
|
})
|
|
|
|
t.Run("should use NoData if NoDataState is not known", func(t *testing.T) {
|
|
rule, err := alertRuleFromModelsAlertRule(g.Generate())
|
|
require.NoError(t, err)
|
|
rule.NoDataState = util.GenerateShortUID()
|
|
|
|
converted, err := alertRuleToModelsAlertRule(rule, &logtest.Fake{})
|
|
require.NoError(t, err)
|
|
require.Equal(t, ngmodels.NoData, converted.NoDataState)
|
|
})
|
|
|
|
t.Run("should use Error if ExecErrState is not known", func(t *testing.T) {
|
|
rule, err := alertRuleFromModelsAlertRule(g.Generate())
|
|
require.NoError(t, err)
|
|
rule.ExecErrState = util.GenerateShortUID()
|
|
|
|
converted, err := alertRuleToModelsAlertRule(rule, &logtest.Fake{})
|
|
require.NoError(t, err)
|
|
require.Equal(t, ngmodels.ErrorErrState, converted.ExecErrState)
|
|
})
|
|
|
|
t.Run("should handle NoGroup rules properly", func(t *testing.T) {
|
|
rule, err := alertRuleFromModelsAlertRule(g.Generate())
|
|
require.NoError(t, err)
|
|
rule.RuleGroup = ""
|
|
projectedRuleGroup, err := ngmodels.NewNoGroupRuleGroup(rule.UID)
|
|
require.NoError(t, err)
|
|
|
|
converted, err := alertRuleToModelsAlertRule(rule, &logtest.Fake{})
|
|
require.NoError(t, err)
|
|
require.Equal(t, projectedRuleGroup.String(), converted.RuleGroup)
|
|
|
|
clone, err := alertRuleFromModelsAlertRule(converted)
|
|
require.NoError(t, err)
|
|
require.Equal(t, rule, clone)
|
|
require.Empty(t, clone.RuleGroup)
|
|
|
|
converted2, err := alertRuleToModelsAlertRule(clone, &logtest.Fake{})
|
|
require.NoError(t, err)
|
|
require.Equal(t, converted, converted2)
|
|
})
|
|
}
|
|
|
|
func TestAlertRuleToModelsAlertRuleCompact(t *testing.T) {
|
|
t.Run("should only extract datasource UIDs in compact mode", func(t *testing.T) {
|
|
rule := alertRule{
|
|
ID: 1,
|
|
OrgID: 1,
|
|
UID: "test-uid",
|
|
Title: "Test Rule",
|
|
Condition: "A",
|
|
Data: `[{"datasourceUid":"ds1","refId":"A","queryType":"test","model":{"expr":"up"}},{"datasourceUid":"ds2","refId":"B","queryType":"test","model":{"expr":"down"}}]`,
|
|
IntervalSeconds: 60,
|
|
Version: 1,
|
|
NamespaceUID: "ns-uid",
|
|
RuleGroup: "test-group",
|
|
NoDataState: "NoData",
|
|
ExecErrState: "Error",
|
|
NotificationSettings: `[{"receiver":"test-receiver"}]`,
|
|
Metadata: `{"editor_settings":{"simplified_query_and_expressions_section":true}}`,
|
|
}
|
|
|
|
compactResult, err := convertAlertRuleToModel(rule, &logtest.Fake{}, AlertRuleConvertOptions{
|
|
ExcludeAlertQueries: true,
|
|
ExcludeNotificationSettings: true,
|
|
ExcludeMetadata: true,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Should have datasource UIDs.
|
|
require.Len(t, compactResult.Data, 2)
|
|
require.Equal(t, "ds1", compactResult.Data[0].DatasourceUID)
|
|
require.Equal(t, "ds2", compactResult.Data[1].DatasourceUID)
|
|
|
|
// But should not have full query data (RefID, QueryType, Model should be empty).
|
|
require.Empty(t, compactResult.Data[0].RefID)
|
|
require.Empty(t, compactResult.Data[0].QueryType)
|
|
require.Nil(t, compactResult.Data[0].Model)
|
|
require.Empty(t, compactResult.Data[1].RefID)
|
|
require.Empty(t, compactResult.Data[1].QueryType)
|
|
require.Nil(t, compactResult.Data[1].Model)
|
|
|
|
// Should not have notification settings.
|
|
require.Empty(t, compactResult.NotificationSettings)
|
|
|
|
// Should not have metadata (should be zero value).
|
|
require.Equal(t, ngmodels.AlertRuleMetadata{}, compactResult.Metadata)
|
|
})
|
|
|
|
t.Run("should parse full data in non-compact mode", func(t *testing.T) {
|
|
rule := alertRule{
|
|
ID: 1,
|
|
OrgID: 1,
|
|
UID: "test-uid",
|
|
Title: "Test Rule",
|
|
Condition: "A",
|
|
Data: `[{"datasourceUid":"ds1","refId":"A","queryType":"test","model":{"expr":"up"}},{"datasourceUid":"ds2","refId":"B","queryType":"test","model":{"expr":"down"}}]`,
|
|
IntervalSeconds: 60,
|
|
Version: 1,
|
|
NamespaceUID: "ns-uid",
|
|
RuleGroup: "test-group",
|
|
NoDataState: "NoData",
|
|
ExecErrState: "Error",
|
|
NotificationSettings: `[{"receiver":"test-receiver"}]`,
|
|
Metadata: `{"editor_settings":{"simplified_query_and_expressions_section":true}}`,
|
|
}
|
|
|
|
fullResult, err := alertRuleToModelsAlertRule(rule, &logtest.Fake{})
|
|
require.NoError(t, err)
|
|
|
|
// Should have full query data.
|
|
require.Len(t, fullResult.Data, 2)
|
|
require.Equal(t, "ds1", fullResult.Data[0].DatasourceUID)
|
|
require.Equal(t, "A", fullResult.Data[0].RefID)
|
|
require.Equal(t, "test", fullResult.Data[0].QueryType)
|
|
require.NotNil(t, fullResult.Data[0].Model)
|
|
|
|
// Should have notification settings.
|
|
require.Len(t, fullResult.NotificationSettings, 1)
|
|
require.Equal(t, "test-receiver", fullResult.NotificationSettings[0].Receiver)
|
|
|
|
// Should have metadata (metadata is parsed from JSON to struct).
|
|
require.NotEqual(t, ngmodels.AlertRuleMetadata{}, fullResult.Metadata)
|
|
})
|
|
|
|
t.Run("compact mode with notification settings included for filtering", func(t *testing.T) {
|
|
rule := alertRule{
|
|
ID: 1,
|
|
OrgID: 1,
|
|
UID: "test-uid",
|
|
Title: "Test Rule",
|
|
Condition: "A",
|
|
Data: `[{"datasourceUid":"ds1","refId":"A","queryType":"test","model":{"expr":"up"}}]`,
|
|
IntervalSeconds: 60,
|
|
Version: 1,
|
|
NamespaceUID: "ns-uid",
|
|
RuleGroup: "test-group",
|
|
NoDataState: "NoData",
|
|
ExecErrState: "Error",
|
|
NotificationSettings: `[{"receiver":"test-receiver"}]`,
|
|
Metadata: `{"editor_settings":{"simplified_query_and_expressions_section":true}}`,
|
|
}
|
|
|
|
result, err := convertAlertRuleToModel(rule, &logtest.Fake{}, AlertRuleConvertOptions{
|
|
ExcludeAlertQueries: true,
|
|
ExcludeNotificationSettings: false,
|
|
ExcludeMetadata: true,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Should have compact query data (only datasource UIDs).
|
|
require.Len(t, result.Data, 1)
|
|
require.Equal(t, "ds1", result.Data[0].DatasourceUID)
|
|
require.Empty(t, result.Data[0].RefID)
|
|
|
|
// Should have notification settings for filtering.
|
|
require.Len(t, result.NotificationSettings, 1)
|
|
require.Equal(t, "test-receiver", result.NotificationSettings[0].Receiver)
|
|
|
|
// Should not have metadata.
|
|
require.Equal(t, ngmodels.AlertRuleMetadata{}, result.Metadata)
|
|
})
|
|
|
|
t.Run("compact mode with metadata included for filtering", func(t *testing.T) {
|
|
rule := alertRule{
|
|
ID: 1,
|
|
OrgID: 1,
|
|
UID: "test-uid",
|
|
Title: "Test Rule",
|
|
Condition: "A",
|
|
Data: `[{"datasourceUid":"ds1","refId":"A","queryType":"test","model":{"expr":"up"}}]`,
|
|
IntervalSeconds: 60,
|
|
Version: 1,
|
|
NamespaceUID: "ns-uid",
|
|
RuleGroup: "test-group",
|
|
NoDataState: "NoData",
|
|
ExecErrState: "Error",
|
|
NotificationSettings: `[{"receiver":"test-receiver"}]`,
|
|
Metadata: `{"prometheus_style_rule":{"original_rule_definition":"alert: TestAlert\n expr: rate(metric[5m]) > 1"}}`,
|
|
}
|
|
|
|
result, err := convertAlertRuleToModel(rule, &logtest.Fake{}, AlertRuleConvertOptions{
|
|
ExcludeAlertQueries: true,
|
|
ExcludeNotificationSettings: true,
|
|
ExcludeMetadata: false,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Should have compact query data (only datasource UIDs).
|
|
require.Len(t, result.Data, 1)
|
|
require.Equal(t, "ds1", result.Data[0].DatasourceUID)
|
|
require.Empty(t, result.Data[0].RefID)
|
|
|
|
// Should not have notification settings.
|
|
require.Empty(t, result.NotificationSettings)
|
|
|
|
// Should have metadata for filtering.
|
|
require.NotEqual(t, ngmodels.AlertRuleMetadata{}, result.Metadata)
|
|
require.True(t, result.HasPrometheusRuleDefinition())
|
|
})
|
|
}
|
|
|
|
func TestAlertRuleVersionToAlertRule(t *testing.T) {
|
|
g := ngmodels.RuleGen
|
|
|
|
t.Run("make sure no data is lost between conversions", func(t *testing.T) {
|
|
for _, rule := range g.GenerateMany(100) {
|
|
// ignore fields
|
|
rule.DashboardUID = nil
|
|
rule.PanelID = nil
|
|
|
|
r, err := alertRuleFromModelsAlertRule(rule)
|
|
require.NoError(t, err)
|
|
r2 := alertRuleVersionToAlertRule(alertRuleToAlertRuleVersion(r))
|
|
require.Equal(t, r, r2)
|
|
}
|
|
})
|
|
}
|