Alerting: Support for active time intervals in notification policies (#104252)
* add active_time_intervals to route model * update k8s compat layer * update notification policies service to validate active time intervals * update integration tests * update openapi * add active time interval to model * update route generator to include active time interval * Update storage list and rename methods to handle active intervals * update api model * update provisioning and export models * update ui to allow active timing config * update i18n * fix snapshots for ui tests * run prettier * Alerting: Active time intervals UI naming (#104402) * update naming in UI * update naming in the edit page title * update translations * update alerting module --------- Signed-off-by: Yuri Tseretyan <yuriy.tseretyan@grafana.com> Co-authored-by: Sonia Aguilar <33540275+soniaAguilarPeiron@users.noreply.github.com> Co-authored-by: Sonia Aguilar <soniaaguilarpeiron@gmail.com>
This commit is contained in:
co-authored by
Sonia Aguilar
Sonia Aguilar
parent
a8dee54aa4
commit
3e2296acd3
@@ -51,13 +51,14 @@ func ConvertToK8sResource(orgID int64, r definitions.Route, version string, name
|
||||
|
||||
func convertRouteToK8sSubRoute(r *definitions.Route) model.Route {
|
||||
result := model.Route{
|
||||
GroupBy: r.GroupByStr,
|
||||
MuteTimeIntervals: r.MuteTimeIntervals,
|
||||
Continue: r.Continue,
|
||||
GroupWait: optionalPrometheusDurationToString(r.GroupWait),
|
||||
GroupInterval: optionalPrometheusDurationToString(r.GroupInterval),
|
||||
RepeatInterval: optionalPrometheusDurationToString(r.RepeatInterval),
|
||||
Routes: make([]model.Route, 0, len(r.Routes)),
|
||||
GroupBy: r.GroupByStr,
|
||||
MuteTimeIntervals: r.MuteTimeIntervals,
|
||||
ActiveTimeIntervals: r.ActiveTimeIntervals,
|
||||
Continue: r.Continue,
|
||||
GroupWait: optionalPrometheusDurationToString(r.GroupWait),
|
||||
GroupInterval: optionalPrometheusDurationToString(r.GroupInterval),
|
||||
RepeatInterval: optionalPrometheusDurationToString(r.RepeatInterval),
|
||||
Routes: make([]model.Route, 0, len(r.Routes)),
|
||||
}
|
||||
if r.Receiver != "" {
|
||||
result.Receiver = util.Pointer(r.Receiver)
|
||||
@@ -152,11 +153,12 @@ func convertToDomainModel(obj *model.RoutingTree) (definitions.Route, string, er
|
||||
|
||||
func convertK8sSubRouteToRoute(r model.Route, path string) (definitions.Route, []error) {
|
||||
result := definitions.Route{
|
||||
GroupByStr: r.GroupBy,
|
||||
MuteTimeIntervals: r.MuteTimeIntervals,
|
||||
Routes: make([]*definitions.Route, 0, len(r.Routes)),
|
||||
Matchers: make(config.Matchers, 0, len(r.Matchers)),
|
||||
Continue: r.Continue,
|
||||
GroupByStr: r.GroupBy,
|
||||
MuteTimeIntervals: r.MuteTimeIntervals,
|
||||
ActiveTimeIntervals: r.ActiveTimeIntervals,
|
||||
Routes: make([]*definitions.Route, 0, len(r.Routes)),
|
||||
Matchers: make(config.Matchers, 0, len(r.Matchers)),
|
||||
Continue: r.Continue,
|
||||
}
|
||||
if r.Receiver != nil {
|
||||
result.Receiver = *r.Receiver
|
||||
|
||||
@@ -630,6 +630,13 @@ func escapeRouteExport(r *definitions.RouteExport) {
|
||||
}
|
||||
r.MuteTimeIntervals = &muteTimeIntervals
|
||||
}
|
||||
if r.ActiveTimeIntervals != nil {
|
||||
intervals := make([]string, len(*r.ActiveTimeIntervals))
|
||||
for i, timeInterval := range *r.ActiveTimeIntervals {
|
||||
intervals[i] = addEscapeCharactersToString(timeInterval)
|
||||
}
|
||||
r.ActiveTimeIntervals = &intervals
|
||||
}
|
||||
for i := range r.Routes {
|
||||
escapeRouteExport(r.Routes[i])
|
||||
}
|
||||
|
||||
@@ -872,7 +872,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
insertRule(t, sut, rule1)
|
||||
insertRule(t, sut, createTestAlertRule("rule2", 1))
|
||||
|
||||
expectedResponse := "apiVersion: 1\ngroups:\n - orgId: 1\n name: my-cool-group\n folder: Folder Title\n interval: 1m\n rules:\n - uid: rule1\n title: rule1\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n - uid: rule2\n title: rule2\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Test-Receiver\n group_by:\n - alertname\n - grafana_folder\n - test\n group_wait: 1s\n group_interval: 5s\n repeat_interval: 5m\n mute_time_intervals:\n - test-mute\n"
|
||||
expectedResponse := "apiVersion: 1\ngroups:\n - orgId: 1\n name: my-cool-group\n folder: Folder Title\n interval: 1m\n rules:\n - uid: rule1\n title: rule1\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n - uid: rule2\n title: rule2\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Test-Receiver\n group_by:\n - alertname\n - grafana_folder\n - test\n group_wait: 1s\n group_interval: 5s\n repeat_interval: 5m\n mute_time_intervals:\n - test-mute\n active_time_intervals:\n - test-active\n"
|
||||
|
||||
response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group")
|
||||
require.Equal(t, 200, response.Status())
|
||||
@@ -888,7 +888,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
insertRule(t, sut, createTestAlertRule("rule2", 1))
|
||||
|
||||
rc.Req.Header.Add("Accept", "application/json")
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"my-cool-group","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false},{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"]}}]}]}`
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"my-cool-group","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false},{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"],"active_time_intervals":["test-active"]}}]}]}`
|
||||
|
||||
response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group")
|
||||
require.Equal(t, 200, response.Status())
|
||||
@@ -902,7 +902,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
insertRule(t, sut, createTestAlertRule("rule2", 1))
|
||||
|
||||
rc.Req.Header.Add("Accept", "application/yaml")
|
||||
expectedResponse := "apiVersion: 1\ngroups:\n - orgId: 1\n name: my-cool-group\n folder: Folder Title\n interval: 1m\n rules:\n - uid: rule1\n title: rule1\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Test-Receiver\n group_by:\n - alertname\n - grafana_folder\n - test\n group_wait: 1s\n group_interval: 5s\n repeat_interval: 5m\n mute_time_intervals:\n - test-mute\n - uid: rule2\n title: rule2\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Test-Receiver\n group_by:\n - alertname\n - grafana_folder\n - test\n group_wait: 1s\n group_interval: 5s\n repeat_interval: 5m\n mute_time_intervals:\n - test-mute\n"
|
||||
expectedResponse := "apiVersion: 1\ngroups:\n - orgId: 1\n name: my-cool-group\n folder: Folder Title\n interval: 1m\n rules:\n - uid: rule1\n title: rule1\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Test-Receiver\n group_by:\n - alertname\n - grafana_folder\n - test\n group_wait: 1s\n group_interval: 5s\n repeat_interval: 5m\n mute_time_intervals:\n - test-mute\n active_time_intervals:\n - test-active\n - uid: rule2\n title: rule2\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Test-Receiver\n group_by:\n - alertname\n - grafana_folder\n - test\n group_wait: 1s\n group_interval: 5s\n repeat_interval: 5m\n mute_time_intervals:\n - test-mute\n active_time_intervals:\n - test-active\n"
|
||||
|
||||
response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group")
|
||||
|
||||
@@ -986,6 +986,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
group_interval = "5s"
|
||||
repeat_interval = "5m"
|
||||
mute_timings = ["test-mute"]
|
||||
active_timings = ["test-active"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1120,7 +1121,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
rc := createTestRequestCtx()
|
||||
insertRule(t, sut, createTestAlertRule("rule1", 1))
|
||||
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"my-cool-group","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"]}}]}]}`
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"my-cool-group","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"],"active_time_intervals":["test-active"]}}]}]}`
|
||||
|
||||
rc.Req.Header.Add("Accept", "application/json")
|
||||
response := sut.RouteGetAlertRuleExport(&rc, "rule1")
|
||||
@@ -1135,7 +1136,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
insertRule(t, sut, createTestAlertRule("rule1", 1))
|
||||
|
||||
rc.Req.Header.Add("Accept", "application/yaml")
|
||||
expectedResponse := "apiVersion: 1\ngroups:\n - orgId: 1\n name: my-cool-group\n folder: Folder Title\n interval: 1m\n rules:\n - uid: rule1\n title: rule1\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Test-Receiver\n group_by:\n - alertname\n - grafana_folder\n - test\n group_wait: 1s\n group_interval: 5s\n repeat_interval: 5m\n mute_time_intervals:\n - test-mute\n"
|
||||
expectedResponse := "apiVersion: 1\ngroups:\n - orgId: 1\n name: my-cool-group\n folder: Folder Title\n interval: 1m\n rules:\n - uid: rule1\n title: rule1\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Test-Receiver\n group_by:\n - alertname\n - grafana_folder\n - test\n group_wait: 1s\n group_interval: 5s\n repeat_interval: 5m\n mute_time_intervals:\n - test-mute\n active_time_intervals:\n - test-active\n"
|
||||
|
||||
response := sut.RouteGetAlertRuleExport(&rc, "rule1")
|
||||
|
||||
@@ -1245,7 +1246,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
insertRule(t, sut, rule3)
|
||||
|
||||
rc.Req.Header.Add("Accept", "application/json")
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Email"}}]},{"orgId":1,"name":"groupb","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"]}}]},{"orgId":1,"name":"groupb","folder":"Folder Title2","interval":"1m","rules":[{"uid":"rule3","title":"rule3","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"]}}]}]}`
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Email"}}]},{"orgId":1,"name":"groupb","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"],"active_time_intervals":["test-active"]}}]},{"orgId":1,"name":"groupb","folder":"Folder Title2","interval":"1m","rules":[{"uid":"rule3","title":"rule3","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"],"active_time_intervals":["test-active"]}}]}]}`
|
||||
|
||||
response := sut.RouteGetAlertRulesExport(&rc)
|
||||
require.Equal(t, 200, response.Status())
|
||||
@@ -1265,7 +1266,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
insertRule(t, sut, rule3)
|
||||
|
||||
rc.Req.Header.Add("Accept", "application/yaml")
|
||||
expectedResponse := "apiVersion: 1\ngroups:\n - orgId: 1\n name: groupa\n folder: Folder Title\n interval: 1m\n rules:\n - uid: rule1\n title: rule1\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Email\n - orgId: 1\n name: groupb\n folder: Folder Title\n interval: 1m\n rules:\n - uid: rule2\n title: rule2\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Test-Receiver\n group_by:\n - alertname\n - grafana_folder\n - test\n group_wait: 1s\n group_interval: 5s\n repeat_interval: 5m\n mute_time_intervals:\n - test-mute\n - orgId: 1\n name: groupb\n folder: Folder Title2\n interval: 1m\n rules:\n - uid: rule3\n title: rule3\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Test-Receiver\n group_by:\n - alertname\n - grafana_folder\n - test\n group_wait: 1s\n group_interval: 5s\n repeat_interval: 5m\n mute_time_intervals:\n - test-mute\n"
|
||||
expectedResponse := "apiVersion: 1\ngroups:\n - orgId: 1\n name: groupa\n folder: Folder Title\n interval: 1m\n rules:\n - uid: rule1\n title: rule1\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Email\n - orgId: 1\n name: groupb\n folder: Folder Title\n interval: 1m\n rules:\n - uid: rule2\n title: rule2\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Test-Receiver\n group_by:\n - alertname\n - grafana_folder\n - test\n group_wait: 1s\n group_interval: 5s\n repeat_interval: 5m\n mute_time_intervals:\n - test-mute\n active_time_intervals:\n - test-active\n - orgId: 1\n name: groupb\n folder: Folder Title2\n interval: 1m\n rules:\n - uid: rule3\n title: rule3\n condition: A\n data:\n - refId: A\n relativeTimeRange:\n from: 60\n to: 0\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n notification_settings:\n receiver: Test-Receiver\n group_by:\n - alertname\n - grafana_folder\n - test\n group_wait: 1s\n group_interval: 5s\n repeat_interval: 5m\n mute_time_intervals:\n - test-mute\n active_time_intervals:\n - test-active\n"
|
||||
|
||||
response := sut.RouteGetAlertRulesExport(&rc)
|
||||
require.Equal(t, 200, response.Status())
|
||||
@@ -1281,7 +1282,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
|
||||
rc.Req.Header.Add("Accept", "application/json")
|
||||
rc.Req.Form.Set("folderUid", "folder-uid")
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"]}}]},{"orgId":1,"name":"groupb","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"]}}]}]}`
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"],"active_time_intervals":["test-active"]}}]},{"orgId":1,"name":"groupb","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"],"active_time_intervals":["test-active"]}}]}]}`
|
||||
|
||||
response := sut.RouteGetAlertRulesExport(&rc)
|
||||
require.Equal(t, 200, response.Status())
|
||||
@@ -1298,7 +1299,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
rc.Req.Header.Add("Accept", "application/json")
|
||||
rc.Req.Form.Set("folder_uid", "folder-uid")
|
||||
rc.Req.Form.Add("folder_uid", "folder-uid2")
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"]}}]},{"orgId":1,"name":"groupb","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"]}}]},{"orgId":1,"name":"groupb","folder":"Folder Title2","interval":"1m","rules":[{"uid":"rule3","title":"rule3","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"]}}]}]}`
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"],"active_time_intervals":["test-active"]}}]},{"orgId":1,"name":"groupb","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"],"active_time_intervals":["test-active"]}}]},{"orgId":1,"name":"groupb","folder":"Folder Title2","interval":"1m","rules":[{"uid":"rule3","title":"rule3","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"],"active_time_intervals":["test-active"]}}]}]}`
|
||||
|
||||
response := sut.RouteGetAlertRulesExport(&rc)
|
||||
require.Equal(t, 200, response.Status())
|
||||
@@ -1316,7 +1317,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
rc.Req.Form.Set("folderUid", "folder-uid")
|
||||
rc.Req.Form.Set("group", "groupa")
|
||||
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"]}}]}]}`
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"],"active_time_intervals":["test-active"]}}]}]}`
|
||||
|
||||
response := sut.RouteGetAlertRulesExport(&rc)
|
||||
require.Equal(t, 200, response.Status())
|
||||
@@ -1354,7 +1355,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
rc.Req.Header.Add("Accept", "application/json")
|
||||
rc.Req.Form.Set("ruleUid", "rule1")
|
||||
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"]}}]}]}`
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":60,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false,"notification_settings":{"receiver":"Test-Receiver","group_by":["alertname","grafana_folder","test"],"group_wait":"1s","group_interval":"5s","repeat_interval":"5m","mute_time_intervals":["test-mute"],"active_time_intervals":["test-active"]}}]}]}`
|
||||
|
||||
response := sut.RouteGetAlertRulesExport(&rc)
|
||||
|
||||
@@ -1471,7 +1472,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
rc := createTestRequestCtx()
|
||||
|
||||
rc.Req.Header.Add("Accept", "application/json")
|
||||
expectedResponse := `{"apiVersion":1,"policies":[{"orgId":1,"receiver":"default-receiver","group_by":["g1","g2"],"routes":[{"receiver":"nested-receiver","group_by":["g3","g4"],"matchers":["a=\"b\""],"object_matchers":[["foo","=","bar"]],"mute_time_intervals":["interval"],"continue":true,"group_wait":"5m","group_interval":"5m","repeat_interval":"5m"}],"group_wait":"30s","group_interval":"5m","repeat_interval":"1h"}]}`
|
||||
expectedResponse := `{"apiVersion":1,"policies":[{"orgId":1,"receiver":"default-receiver","group_by":["g1","g2"],"routes":[{"receiver":"nested-receiver","group_by":["g3","g4"],"matchers":["a=\"b\""],"object_matchers":[["foo","=","bar"]],"mute_time_intervals":["interval"],"active_time_intervals":["active"],"continue":true,"group_wait":"5m","group_interval":"5m","repeat_interval":"5m"}],"group_wait":"30s","group_interval":"5m","repeat_interval":"1h"}]}`
|
||||
|
||||
response := sut.RouteGetPolicyTreeExport(&rc)
|
||||
|
||||
@@ -1485,7 +1486,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
rc := createTestRequestCtx()
|
||||
|
||||
rc.Req.Header.Add("Accept", "application/yaml")
|
||||
expectedResponse := "apiVersion: 1\npolicies:\n - orgId: 1\n receiver: default-receiver\n group_by:\n - g1\n - g2\n routes:\n - receiver: nested-receiver\n group_by:\n - g3\n - g4\n matchers:\n - a=\"b\"\n object_matchers:\n - - foo\n - =\n - bar\n mute_time_intervals:\n - interval\n continue: true\n group_wait: 5m\n group_interval: 5m\n repeat_interval: 5m\n group_wait: 30s\n group_interval: 5m\n repeat_interval: 1h\n"
|
||||
expectedResponse := "apiVersion: 1\npolicies:\n - orgId: 1\n receiver: default-receiver\n group_by:\n - g1\n - g2\n routes:\n - receiver: nested-receiver\n group_by:\n - g3\n - g4\n matchers:\n - a=\"b\"\n object_matchers:\n - - foo\n - =\n - bar\n mute_time_intervals:\n - interval\n active_time_intervals:\n - active\n continue: true\n group_wait: 5m\n group_interval: 5m\n repeat_interval: 5m\n group_wait: 30s\n group_interval: 5m\n repeat_interval: 1h\n"
|
||||
|
||||
response := sut.RouteGetPolicyTreeExport(&rc)
|
||||
|
||||
@@ -1499,7 +1500,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
rc := createTestRequestCtx()
|
||||
|
||||
rc.Req.Form.Add("format", "hcl")
|
||||
expectedResponse := "resource \"grafana_notification_policy\" \"notification_policy_1\" {\n contact_point = \"default-receiver\"\n group_by = [\"g1\", \"g2\"]\n\n policy {\n contact_point = \"nested-receiver\"\n group_by = [\"g3\", \"g4\"]\n\n matcher {\n label = \"foo\"\n match = \"=\"\n value = \"bar\"\n }\n\n mute_timings = [\"interval\"]\n continue = true\n group_wait = \"5m\"\n group_interval = \"5m\"\n repeat_interval = \"5m\"\n }\n\n group_wait = \"30s\"\n group_interval = \"5m\"\n repeat_interval = \"1h\"\n}\n"
|
||||
expectedResponse := "resource \"grafana_notification_policy\" \"notification_policy_1\" {\n contact_point = \"default-receiver\"\n group_by = [\"g1\", \"g2\"]\n\n policy {\n contact_point = \"nested-receiver\"\n group_by = [\"g3\", \"g4\"]\n\n matcher {\n label = \"foo\"\n match = \"=\"\n value = \"bar\"\n }\n\n mute_timings = [\"interval\"]\n active_timings = [\"active\"]\n continue = true\n group_wait = \"5m\"\n group_interval = \"5m\"\n repeat_interval = \"5m\"\n }\n\n group_wait = \"30s\"\n group_interval = \"5m\"\n repeat_interval = \"1h\"\n}\n"
|
||||
|
||||
response := sut.RouteGetPolicyTreeExport(&rc)
|
||||
|
||||
@@ -2152,12 +2153,13 @@ func createFakeNotificationPolicyService() *fakeNotificationPolicyService {
|
||||
Value: "b",
|
||||
},
|
||||
},
|
||||
ObjectMatchers: definitions.ObjectMatchers{{Type: 0, Name: "foo", Value: "bar"}},
|
||||
MuteTimeIntervals: []string{"interval"},
|
||||
Continue: true,
|
||||
GroupWait: &minutes,
|
||||
GroupInterval: &minutes,
|
||||
RepeatInterval: &minutes,
|
||||
ObjectMatchers: definitions.ObjectMatchers{{Type: 0, Name: "foo", Value: "bar"}},
|
||||
MuteTimeIntervals: []string{"interval"},
|
||||
ActiveTimeIntervals: []string{"active"},
|
||||
Continue: true,
|
||||
GroupWait: &minutes,
|
||||
GroupInterval: &minutes,
|
||||
RepeatInterval: &minutes,
|
||||
}},
|
||||
},
|
||||
prov: models.ProvenanceAPI,
|
||||
@@ -2297,12 +2299,13 @@ func createTestAlertRule(title string, orgID int64) definitions.ProvisionedAlert
|
||||
NoDataState: definitions.OK,
|
||||
ExecErrState: definitions.OkErrState,
|
||||
NotificationSettings: &definitions.AlertRuleNotificationSettings{
|
||||
Receiver: "Test-Receiver",
|
||||
GroupBy: []string{"alertname", "grafana_folder", "test"},
|
||||
GroupWait: util.Pointer(model.Duration(1 * time.Second)),
|
||||
GroupInterval: util.Pointer(model.Duration(5 * time.Second)),
|
||||
RepeatInterval: util.Pointer(model.Duration(5 * time.Minute)),
|
||||
MuteTimeIntervals: []string{"test-mute"},
|
||||
Receiver: "Test-Receiver",
|
||||
GroupBy: []string{"alertname", "grafana_folder", "test"},
|
||||
GroupWait: util.Pointer(model.Duration(1 * time.Second)),
|
||||
GroupInterval: util.Pointer(model.Duration(5 * time.Second)),
|
||||
RepeatInterval: util.Pointer(model.Duration(5 * time.Minute)),
|
||||
MuteTimeIntervals: []string{"test-mute"},
|
||||
ActiveTimeIntervals: []string{"test-active"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,6 +367,7 @@ func RouteExportFromRoute(route *definitions.Route) *definitions.RouteExport {
|
||||
ObjectMatchers: route.ObjectMatchers,
|
||||
ObjectMatchersSlice: matchers,
|
||||
MuteTimeIntervals: NilIfEmpty(util.Pointer(route.MuteTimeIntervals)),
|
||||
ActiveTimeIntervals: NilIfEmpty(util.Pointer(route.ActiveTimeIntervals)),
|
||||
Continue: OmitDefault(util.Pointer(route.Continue)),
|
||||
GroupWait: toStringIfNotNil(route.GroupWait),
|
||||
GroupInterval: toStringIfNotNil(route.GroupInterval),
|
||||
@@ -455,12 +456,13 @@ func AlertRuleNotificationSettingsFromNotificationSettings(ns []models.Notificat
|
||||
}
|
||||
m := ns[0]
|
||||
return &definitions.AlertRuleNotificationSettings{
|
||||
Receiver: m.Receiver,
|
||||
GroupBy: m.GroupBy,
|
||||
GroupWait: m.GroupWait,
|
||||
GroupInterval: m.GroupInterval,
|
||||
RepeatInterval: m.RepeatInterval,
|
||||
MuteTimeIntervals: m.MuteTimeIntervals,
|
||||
Receiver: m.Receiver,
|
||||
GroupBy: m.GroupBy,
|
||||
GroupWait: m.GroupWait,
|
||||
GroupInterval: m.GroupInterval,
|
||||
RepeatInterval: m.RepeatInterval,
|
||||
MuteTimeIntervals: m.MuteTimeIntervals,
|
||||
ActiveTimeIntervals: m.ActiveTimeIntervals,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,12 +482,13 @@ func AlertRuleNotificationSettingsExportFromNotificationSettings(ns []models.Not
|
||||
}
|
||||
|
||||
return &definitions.AlertRuleNotificationSettingsExport{
|
||||
Receiver: m.Receiver,
|
||||
GroupBy: m.GroupBy,
|
||||
GroupWait: toStringIfNotNil(m.GroupWait),
|
||||
GroupInterval: toStringIfNotNil(m.GroupInterval),
|
||||
RepeatInterval: toStringIfNotNil(m.RepeatInterval),
|
||||
MuteTimeIntervals: m.MuteTimeIntervals,
|
||||
Receiver: m.Receiver,
|
||||
GroupBy: m.GroupBy,
|
||||
GroupWait: toStringIfNotNil(m.GroupWait),
|
||||
GroupInterval: toStringIfNotNil(m.GroupInterval),
|
||||
RepeatInterval: toStringIfNotNil(m.RepeatInterval),
|
||||
MuteTimeIntervals: m.MuteTimeIntervals,
|
||||
ActiveTimeIntervals: m.ActiveTimeIntervals,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,12 +499,13 @@ func NotificationSettingsFromAlertRuleNotificationSettings(ns *definitions.Alert
|
||||
}
|
||||
return []models.NotificationSettings{
|
||||
{
|
||||
Receiver: ns.Receiver,
|
||||
GroupBy: ns.GroupBy,
|
||||
GroupWait: ns.GroupWait,
|
||||
GroupInterval: ns.GroupInterval,
|
||||
RepeatInterval: ns.RepeatInterval,
|
||||
MuteTimeIntervals: ns.MuteTimeIntervals,
|
||||
Receiver: ns.Receiver,
|
||||
GroupBy: ns.GroupBy,
|
||||
GroupWait: ns.GroupWait,
|
||||
GroupInterval: ns.GroupInterval,
|
||||
RepeatInterval: ns.RepeatInterval,
|
||||
MuteTimeIntervals: ns.MuteTimeIntervals,
|
||||
ActiveTimeIntervals: ns.ActiveTimeIntervals,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ resource "grafana_rule_group" "rule_group_d3e8424bfbf66bc3" {
|
||||
group_interval = "5s"
|
||||
repeat_interval = "5m"
|
||||
mute_timings = ["test-mute"]
|
||||
active_timings = ["test-mute"]
|
||||
}
|
||||
}
|
||||
rule {
|
||||
@@ -125,6 +126,7 @@ resource "grafana_rule_group" "rule_group_d3e8424bfbf66bc3" {
|
||||
group_interval = "5s"
|
||||
repeat_interval = "5m"
|
||||
mute_timings = ["test-mute"]
|
||||
active_timings = ["test-mute"]
|
||||
}
|
||||
}
|
||||
rule {
|
||||
|
||||
@@ -115,7 +115,8 @@
|
||||
"group_wait":"1s",
|
||||
"group_interval":"5s",
|
||||
"repeat_interval":"5m",
|
||||
"mute_time_intervals":["test-mute"]
|
||||
"mute_time_intervals":["test-mute"],
|
||||
"active_time_intervals":["test-mute"]
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -169,7 +170,8 @@
|
||||
"group_wait":"1s",
|
||||
"group_interval":"5s",
|
||||
"repeat_interval":"5m",
|
||||
"mute_time_intervals":["test-mute"]
|
||||
"mute_time_intervals":["test-mute"],
|
||||
"active_time_intervals":["test-mute"]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -93,6 +93,8 @@ groups:
|
||||
repeat_interval: 5m
|
||||
mute_time_intervals:
|
||||
- test-mute
|
||||
active_time_intervals:
|
||||
- test-mute
|
||||
- uid: alert-with-uid
|
||||
title: alert with uid
|
||||
condition: B
|
||||
@@ -139,6 +141,8 @@ groups:
|
||||
repeat_interval: 5m
|
||||
mute_time_intervals:
|
||||
- test-mute
|
||||
active_time_intervals:
|
||||
- test-mute
|
||||
- title: recording rule
|
||||
data:
|
||||
- refId: query
|
||||
|
||||
@@ -116,7 +116,8 @@
|
||||
"group_wait":"1s",
|
||||
"group_interval":"5s",
|
||||
"repeat_interval":"5m",
|
||||
"mute_time_intervals":["test-mute"]
|
||||
"mute_time_intervals":["test-mute"],
|
||||
"active_time_intervals":["test-mute"]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -171,7 +172,8 @@
|
||||
"group_wait":"1s",
|
||||
"group_interval":"5s",
|
||||
"repeat_interval":"5m",
|
||||
"mute_time_intervals":["test-mute"]
|
||||
"mute_time_intervals":["test-mute"],
|
||||
"active_time_intervals":["test-mute"]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -535,10 +535,16 @@ type AlertRuleNotificationSettings struct {
|
||||
RepeatInterval *model.Duration `json:"repeat_interval,omitempty"`
|
||||
|
||||
// Override the times when notifications should be muted. These must match the name of a mute time interval defined
|
||||
// in the alertmanager configuration mute_time_intervals section. When muted it will not send any notifications, but
|
||||
// in the alertmanager configuration time_intervals section. When muted it will not send any notifications, but
|
||||
// otherwise acts normally.
|
||||
// example: ["maintenance"]
|
||||
MuteTimeIntervals []string `json:"mute_time_intervals,omitempty"`
|
||||
|
||||
// Override the times when notifications should not be muted. These must match the name of a mute time interval defined
|
||||
// in the alertmanager configuration time_intervals section. All notifications will be suppressed unless they are sent
|
||||
// at the time that matches any interval.
|
||||
// example: ["maintenance"]
|
||||
ActiveTimeIntervals []string `json:"active_time_intervals,omitempty"`
|
||||
}
|
||||
|
||||
// swagger:model
|
||||
|
||||
@@ -171,7 +171,7 @@ type ProvisionedAlertRule struct {
|
||||
IsPaused bool `json:"isPaused"`
|
||||
// example: {"receiver":"email","group_by":["alertname","grafana_folder","cluster"],"group_wait":"30s","group_interval":"1m","repeat_interval":"4d","mute_time_intervals":["Weekends","Holidays"]}
|
||||
NotificationSettings *AlertRuleNotificationSettings `json:"notification_settings"`
|
||||
//example: {"metric":"grafana_alerts_ratio", "from":"A"}
|
||||
// example: {"metric":"grafana_alerts_ratio", "from":"A"}
|
||||
Record *Record `json:"record"`
|
||||
// example: 2
|
||||
MissingSeriesEvalsToResolve *int `json:"missingSeriesEvalsToResolve,omitempty"`
|
||||
@@ -306,12 +306,13 @@ type RelativeTimeRangeExport struct {
|
||||
type AlertRuleNotificationSettingsExport struct {
|
||||
// Field name mismatches with Terraform provider schema are noted where applicable.
|
||||
|
||||
Receiver string `yaml:"receiver,omitempty" json:"receiver,omitempty" hcl:"contact_point"` // TF -> `contact_point`
|
||||
GroupBy []string `yaml:"group_by,omitempty" json:"group_by,omitempty" hcl:"group_by"`
|
||||
GroupWait *string `yaml:"group_wait,omitempty" json:"group_wait,omitempty" hcl:"group_wait,optional"`
|
||||
GroupInterval *string `yaml:"group_interval,omitempty" json:"group_interval,omitempty" hcl:"group_interval,optional"`
|
||||
RepeatInterval *string `yaml:"repeat_interval,omitempty" json:"repeat_interval,omitempty" hcl:"repeat_interval,optional"`
|
||||
MuteTimeIntervals []string `yaml:"mute_time_intervals,omitempty" json:"mute_time_intervals,omitempty" hcl:"mute_timings"` // TF -> `mute_timings`
|
||||
Receiver string `yaml:"receiver,omitempty" json:"receiver,omitempty" hcl:"contact_point"` // TF -> `contact_point`
|
||||
GroupBy []string `yaml:"group_by,omitempty" json:"group_by,omitempty" hcl:"group_by"`
|
||||
GroupWait *string `yaml:"group_wait,omitempty" json:"group_wait,omitempty" hcl:"group_wait,optional"`
|
||||
GroupInterval *string `yaml:"group_interval,omitempty" json:"group_interval,omitempty" hcl:"group_interval,optional"`
|
||||
RepeatInterval *string `yaml:"repeat_interval,omitempty" json:"repeat_interval,omitempty" hcl:"repeat_interval,optional"`
|
||||
MuteTimeIntervals []string `yaml:"mute_time_intervals,omitempty" json:"mute_time_intervals,omitempty" hcl:"mute_timings"` // TF -> `mute_timings`
|
||||
ActiveTimeIntervals []string `yaml:"active_time_intervals,omitempty" json:"active_time_intervals,omitempty" hcl:"active_timings"` // TF -> `active_timings`
|
||||
}
|
||||
|
||||
// Record is the provisioned export of models.Record.
|
||||
|
||||
@@ -81,6 +81,7 @@ type RouteExport struct {
|
||||
ObjectMatchers ObjectMatchers `yaml:"object_matchers,omitempty" json:"object_matchers,omitempty"`
|
||||
ObjectMatchersSlice []*MatcherExport `yaml:"-" json:"-" hcl:"matcher,block"`
|
||||
MuteTimeIntervals *[]string `yaml:"mute_time_intervals,omitempty" json:"mute_time_intervals,omitempty" hcl:"mute_timings"`
|
||||
ActiveTimeIntervals *[]string `yaml:"active_time_intervals,omitempty" json:"active_time_intervals,omitempty" hcl:"active_timings"`
|
||||
Continue *bool `yaml:"continue,omitempty" json:"continue,omitempty" hcl:"continue,optional"` // Added omitempty to yaml for a cleaner export.
|
||||
Routes []*RouteExport `yaml:"routes,omitempty" json:"routes,omitempty" hcl:"policy,block"`
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
prommodels "github.com/prometheus/common/model"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
. "github.com/grafana/grafana/pkg/services/ngalert/api/compat"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
@@ -14,7 +16,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
prommodels "github.com/prometheus/common/model"
|
||||
)
|
||||
|
||||
type RuleLimits struct {
|
||||
@@ -392,12 +393,13 @@ func ValidateRuleGroup(
|
||||
|
||||
func validateNotificationSettings(n *apimodels.AlertRuleNotificationSettings) ([]ngmodels.NotificationSettings, error) {
|
||||
s := ngmodels.NotificationSettings{
|
||||
Receiver: n.Receiver,
|
||||
GroupBy: n.GroupBy,
|
||||
GroupWait: n.GroupWait,
|
||||
GroupInterval: n.GroupInterval,
|
||||
RepeatInterval: n.RepeatInterval,
|
||||
MuteTimeIntervals: n.MuteTimeIntervals,
|
||||
Receiver: n.Receiver,
|
||||
GroupBy: n.GroupBy,
|
||||
GroupWait: n.GroupWait,
|
||||
GroupInterval: n.GroupInterval,
|
||||
RepeatInterval: n.RepeatInterval,
|
||||
MuteTimeIntervals: n.MuteTimeIntervals,
|
||||
ActiveTimeIntervals: n.ActiveTimeIntervals,
|
||||
}
|
||||
|
||||
if err := s.Validate(); err != nil {
|
||||
|
||||
@@ -850,6 +850,22 @@ func TestDiff(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "should detect changes in ActiveTimeIntervals",
|
||||
notificationSettings: CopyNotificationSettings(baseSettings, NSMuts.WithActiveTimeIntervals(baseSettings.ActiveTimeIntervals[0]+"-modified", baseSettings.ActiveTimeIntervals[1]+"-modified")),
|
||||
diffs: []cmputil.Diff{
|
||||
{
|
||||
Path: "NotificationSettings[0].ActiveTimeIntervals[0]",
|
||||
Left: reflect.ValueOf(baseSettings.ActiveTimeIntervals[0]),
|
||||
Right: reflect.ValueOf(baseSettings.ActiveTimeIntervals[0] + "-modified"),
|
||||
},
|
||||
{
|
||||
Path: "NotificationSettings[0].ActiveTimeIntervals[1]",
|
||||
Left: reflect.ValueOf(baseSettings.ActiveTimeIntervals[1]),
|
||||
Right: reflect.ValueOf(baseSettings.ActiveTimeIntervals[1] + "-modified"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
|
||||
@@ -28,11 +28,12 @@ type ListNotificationSettingsQuery struct {
|
||||
type NotificationSettings struct {
|
||||
Receiver string `json:"receiver"`
|
||||
|
||||
GroupBy []string `json:"group_by,omitempty"`
|
||||
GroupWait *model.Duration `json:"group_wait,omitempty"`
|
||||
GroupInterval *model.Duration `json:"group_interval,omitempty"`
|
||||
RepeatInterval *model.Duration `json:"repeat_interval,omitempty"`
|
||||
MuteTimeIntervals []string `json:"mute_time_intervals,omitempty"`
|
||||
GroupBy []string `json:"group_by,omitempty"`
|
||||
GroupWait *model.Duration `json:"group_wait,omitempty"`
|
||||
GroupInterval *model.Duration `json:"group_interval,omitempty"`
|
||||
RepeatInterval *model.Duration `json:"repeat_interval,omitempty"`
|
||||
MuteTimeIntervals []string `json:"mute_time_intervals,omitempty"`
|
||||
ActiveTimeIntervals []string `json:"active_time_intervals,omitempty"`
|
||||
}
|
||||
|
||||
func (s *NotificationSettings) GetUID() string {
|
||||
@@ -136,6 +137,9 @@ func (s *NotificationSettings) Equals(other *NotificationSettings) bool {
|
||||
if !slices.Equal(s.MuteTimeIntervals, other.MuteTimeIntervals) {
|
||||
return false
|
||||
}
|
||||
if !slices.Equal(s.ActiveTimeIntervals, other.ActiveTimeIntervals) {
|
||||
return false
|
||||
}
|
||||
sGr := s.GroupBy
|
||||
oGr := other.GroupBy
|
||||
return slices.Equal(sGr, oGr)
|
||||
@@ -143,7 +147,7 @@ func (s *NotificationSettings) Equals(other *NotificationSettings) bool {
|
||||
|
||||
// IsAllDefault checks if the NotificationSettings object has all default values for optional fields (all except Receiver) .
|
||||
func (s *NotificationSettings) IsAllDefault() bool {
|
||||
return len(s.GroupBy) == 0 && s.GroupWait == nil && s.GroupInterval == nil && s.RepeatInterval == nil && len(s.MuteTimeIntervals) == 0
|
||||
return len(s.GroupBy) == 0 && s.GroupWait == nil && s.GroupInterval == nil && s.RepeatInterval == nil && len(s.MuteTimeIntervals) == 0 && len(s.ActiveTimeIntervals) == 0
|
||||
}
|
||||
|
||||
// NewDefaultNotificationSettings creates a new default NotificationSettings with the specified receiver.
|
||||
@@ -186,5 +190,8 @@ func (s *NotificationSettings) Fingerprint() data.Fingerprint {
|
||||
for _, interval := range s.MuteTimeIntervals {
|
||||
writeString(interval)
|
||||
}
|
||||
for _, interval := range s.ActiveTimeIntervals {
|
||||
writeString(interval)
|
||||
}
|
||||
return data.Fingerprint(h.Sum64())
|
||||
}
|
||||
|
||||
@@ -154,6 +154,23 @@ func TestNotificationSettingsLabels(t *testing.T) {
|
||||
AutogeneratedRouteSettingsHashLabel: "47164c92f2986a35",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "custom notification settings with active time interval",
|
||||
notificationSettings: NotificationSettings{
|
||||
Receiver: "receiver name",
|
||||
GroupBy: []string{"label1", "label2"},
|
||||
GroupWait: util.Pointer(model.Duration(1 * time.Minute)),
|
||||
GroupInterval: util.Pointer(model.Duration(2 * time.Minute)),
|
||||
RepeatInterval: util.Pointer(model.Duration(3 * time.Minute)),
|
||||
MuteTimeIntervals: []string{"maintenance1", "maintenance2"},
|
||||
ActiveTimeIntervals: []string{"active1", "active2"},
|
||||
},
|
||||
labels: data.Labels{
|
||||
AutogeneratedRouteLabel: "true",
|
||||
AutogeneratedRouteReceiverNameLabel: "receiver name",
|
||||
AutogeneratedRouteSettingsHashLabel: "a173df6210e43af0",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
|
||||
@@ -925,6 +925,10 @@ func CopyNotificationSettings(ns NotificationSettings, mutators ...Mutator[Notif
|
||||
c.MuteTimeIntervals = make([]string, len(ns.MuteTimeIntervals))
|
||||
copy(c.MuteTimeIntervals, ns.MuteTimeIntervals)
|
||||
}
|
||||
if ns.ActiveTimeIntervals != nil {
|
||||
c.ActiveTimeIntervals = make([]string, len(ns.ActiveTimeIntervals))
|
||||
copy(c.ActiveTimeIntervals, ns.ActiveTimeIntervals)
|
||||
}
|
||||
for _, mutator := range mutators {
|
||||
mutator(&c)
|
||||
}
|
||||
@@ -935,12 +939,13 @@ func CopyNotificationSettings(ns NotificationSettings, mutators ...Mutator[Notif
|
||||
func NotificationSettingsGen(mutators ...Mutator[NotificationSettings]) func() NotificationSettings {
|
||||
return func() NotificationSettings {
|
||||
c := NotificationSettings{
|
||||
Receiver: util.GenerateShortUID(),
|
||||
GroupBy: []string{model.AlertNameLabel, FolderTitleLabel, util.GenerateShortUID()},
|
||||
GroupWait: util.Pointer(model.Duration(time.Duration(rand.Intn(100)+1) * time.Second)),
|
||||
GroupInterval: util.Pointer(model.Duration(time.Duration(rand.Intn(100)+1) * time.Second)),
|
||||
RepeatInterval: util.Pointer(model.Duration(time.Duration(rand.Intn(100)+1) * time.Second)),
|
||||
MuteTimeIntervals: []string{util.GenerateShortUID(), util.GenerateShortUID()},
|
||||
Receiver: util.GenerateShortUID(),
|
||||
GroupBy: []string{model.AlertNameLabel, FolderTitleLabel, util.GenerateShortUID()},
|
||||
GroupWait: util.Pointer(model.Duration(time.Duration(rand.Intn(100)+1) * time.Second)),
|
||||
GroupInterval: util.Pointer(model.Duration(time.Duration(rand.Intn(100)+1) * time.Second)),
|
||||
RepeatInterval: util.Pointer(model.Duration(time.Duration(rand.Intn(100)+1) * time.Second)),
|
||||
MuteTimeIntervals: []string{util.GenerateShortUID(), util.GenerateShortUID()},
|
||||
ActiveTimeIntervals: []string{util.GenerateShortUID(), util.GenerateShortUID()},
|
||||
}
|
||||
for _, mutator := range mutators {
|
||||
mutator(&c)
|
||||
@@ -1002,6 +1007,12 @@ func (n NotificationSettingsMutators) WithMuteTimeIntervals(muteTimeIntervals ..
|
||||
}
|
||||
}
|
||||
|
||||
func (n NotificationSettingsMutators) WithActiveTimeIntervals(activeTimeIntervals ...string) Mutator[NotificationSettings] {
|
||||
return func(ns *NotificationSettings) {
|
||||
ns.ActiveTimeIntervals = activeTimeIntervals
|
||||
}
|
||||
}
|
||||
|
||||
// Silences
|
||||
|
||||
// CopySilenceWith creates a deep copy of Silence and then applies mutators to it.
|
||||
|
||||
@@ -146,13 +146,14 @@ func generateRouteFromSettings(defaultReceiver string, settings map[data.Fingerp
|
||||
ObjectMatchers: definitions.ObjectMatchers{settingMatcher},
|
||||
Continue: false, // Only a single setting-specific route should match.
|
||||
|
||||
GroupByStr: normalized,
|
||||
GroupBy: groupBy,
|
||||
GroupByAll: groupByAll,
|
||||
MuteTimeIntervals: s.MuteTimeIntervals,
|
||||
GroupWait: s.GroupWait,
|
||||
GroupInterval: s.GroupInterval,
|
||||
RepeatInterval: s.RepeatInterval,
|
||||
GroupByStr: normalized,
|
||||
GroupBy: groupBy,
|
||||
GroupByAll: groupByAll,
|
||||
MuteTimeIntervals: s.MuteTimeIntervals,
|
||||
ActiveTimeIntervals: s.ActiveTimeIntervals,
|
||||
GroupWait: s.GroupWait,
|
||||
GroupInterval: s.GroupInterval,
|
||||
RepeatInterval: s.RepeatInterval,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -108,20 +108,22 @@ func TestAddAutogenConfig(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "settings with custom options, add option-specific routes",
|
||||
existingConfig: configGen([]string{"receiver1", "receiver2", "receiver3", "receiver4", "receiver5"}, []string{"maintenance"}),
|
||||
existingConfig: configGen([]string{"receiver1", "receiver2", "receiver3", "receiver4", "receiver5"}, []string{"maintenance", "active"}),
|
||||
storeSettings: []models.NotificationSettings{
|
||||
models.CopyNotificationSettings(models.NewDefaultNotificationSettings("receiver1"), models.NSMuts.WithGroupInterval(util.Pointer(1*time.Minute))),
|
||||
models.CopyNotificationSettings(models.NewDefaultNotificationSettings("receiver2"), models.NSMuts.WithGroupWait(util.Pointer(2*time.Minute))),
|
||||
models.CopyNotificationSettings(models.NewDefaultNotificationSettings("receiver3"), models.NSMuts.WithRepeatInterval(util.Pointer(3*time.Minute))),
|
||||
models.CopyNotificationSettings(models.NewDefaultNotificationSettings("receiver4"), models.NSMuts.WithGroupBy(model.AlertNameLabel, models.FolderTitleLabel, "custom")),
|
||||
models.CopyNotificationSettings(models.NewDefaultNotificationSettings("receiver5"), models.NSMuts.WithMuteTimeIntervals("maintenance")),
|
||||
models.CopyNotificationSettings(models.NewDefaultNotificationSettings("receiver5"), models.NSMuts.WithActiveTimeIntervals("active")),
|
||||
{
|
||||
Receiver: "receiver1",
|
||||
GroupBy: []string{model.AlertNameLabel, models.FolderTitleLabel, "custom"},
|
||||
GroupInterval: util.Pointer(model.Duration(1 * time.Minute)),
|
||||
GroupWait: util.Pointer(model.Duration(2 * time.Minute)),
|
||||
RepeatInterval: util.Pointer(model.Duration(3 * time.Minute)),
|
||||
MuteTimeIntervals: []string{"maintenance"},
|
||||
Receiver: "receiver1",
|
||||
GroupBy: []string{model.AlertNameLabel, models.FolderTitleLabel, "custom"},
|
||||
GroupInterval: util.Pointer(model.Duration(1 * time.Minute)),
|
||||
GroupWait: util.Pointer(model.Duration(2 * time.Minute)),
|
||||
RepeatInterval: util.Pointer(model.Duration(3 * time.Minute)),
|
||||
MuteTimeIntervals: []string{"maintenance"},
|
||||
ActiveTimeIntervals: []string{"active"},
|
||||
},
|
||||
},
|
||||
expRoute: withChildRoutes(rootRoute(), &definitions.Route{
|
||||
@@ -132,19 +134,24 @@ func TestAddAutogenConfig(t *testing.T) {
|
||||
Receiver: "receiver5",
|
||||
ObjectMatchers: matcher(models.AutogeneratedRouteSettingsHashLabel, "030d6474aec0b553"),
|
||||
MuteTimeIntervals: []string{"maintenance"},
|
||||
}, &definitions.Route{
|
||||
Receiver: "receiver5",
|
||||
ObjectMatchers: matcher(models.AutogeneratedRouteSettingsHashLabel, "cd6cd2089632453c"),
|
||||
ActiveTimeIntervals: []string{"active"},
|
||||
}),
|
||||
withChildRoutes(basicContactRoute("receiver1"), &definitions.Route{
|
||||
Receiver: "receiver1",
|
||||
ObjectMatchers: matcher(models.AutogeneratedRouteSettingsHashLabel, "4f095749ddf3eeeb"),
|
||||
GroupByStr: []string{models.FolderTitleLabel, model.AlertNameLabel, "custom"},
|
||||
GroupInterval: util.Pointer(model.Duration(1 * time.Minute)),
|
||||
GroupWait: util.Pointer(model.Duration(2 * time.Minute)),
|
||||
RepeatInterval: util.Pointer(model.Duration(3 * time.Minute)),
|
||||
MuteTimeIntervals: []string{"maintenance"},
|
||||
}, &definitions.Route{
|
||||
Receiver: "receiver1",
|
||||
ObjectMatchers: matcher(models.AutogeneratedRouteSettingsHashLabel, "dde34b8127e68f31"),
|
||||
GroupInterval: util.Pointer(model.Duration(1 * time.Minute)),
|
||||
}, &definitions.Route{
|
||||
Receiver: "receiver1",
|
||||
ObjectMatchers: matcher(models.AutogeneratedRouteSettingsHashLabel, "f134b8faf7db083c"),
|
||||
GroupByStr: []string{models.FolderTitleLabel, model.AlertNameLabel, "custom"},
|
||||
GroupInterval: util.Pointer(model.Duration(1 * time.Minute)),
|
||||
GroupWait: util.Pointer(model.Duration(2 * time.Minute)),
|
||||
RepeatInterval: util.Pointer(model.Duration(3 * time.Minute)),
|
||||
MuteTimeIntervals: []string{"maintenance"},
|
||||
ActiveTimeIntervals: []string{"active"},
|
||||
}),
|
||||
withChildRoutes(basicContactRoute("receiver2"), &definitions.Route{
|
||||
Receiver: "receiver2",
|
||||
|
||||
@@ -91,6 +91,11 @@ func (n staticValidator) Validate(settings models.NotificationSettings) error {
|
||||
errs = append(errs, ErrorTimeIntervalDoesNotExist{ErrorReferenceInvalid: ErrorReferenceInvalid{Reference: interval}})
|
||||
}
|
||||
}
|
||||
for _, interval := range settings.ActiveTimeIntervals {
|
||||
if _, ok := n.availableTimeIntervals[interval]; !ok {
|
||||
errs = append(errs, ErrorTimeIntervalDoesNotExist{ErrorReferenceInvalid: ErrorReferenceInvalid{Reference: interval}})
|
||||
}
|
||||
}
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ func (nps *NotificationPolicyService) UpdatePolicyTree(ctx context.Context, orgI
|
||||
for _, mt := range revision.Config.AlertmanagerConfig.TimeIntervals {
|
||||
timeIntervals[mt.Name] = struct{}{}
|
||||
}
|
||||
err = tree.ValidateMuteTimes(timeIntervals)
|
||||
err = tree.ValidateTimeIntervals(timeIntervals)
|
||||
if err != nil {
|
||||
return definitions.Route{}, "", MakeErrRouteInvalidFormat(err)
|
||||
}
|
||||
|
||||
@@ -92,6 +92,21 @@ func TestUpdatePolicyTree(t *testing.T) {
|
||||
require.ErrorIs(t, err, ErrRouteInvalidFormat)
|
||||
})
|
||||
|
||||
t.Run("ErrValidation if referenced active time interval does not exist", func(t *testing.T) {
|
||||
sut, store, _ := createNotificationPolicyServiceSut()
|
||||
store.GetFn = func(ctx context.Context, orgID int64) (*legacy_storage.ConfigRevision, error) {
|
||||
return &rev, nil
|
||||
}
|
||||
newRoute := definitions.Route{
|
||||
Receiver: rev.Config.AlertmanagerConfig.Receivers[0].Name,
|
||||
ActiveTimeIntervals: []string{
|
||||
"not-existing",
|
||||
},
|
||||
}
|
||||
_, _, err := sut.UpdatePolicyTree(context.Background(), orgID, newRoute, models.ProvenanceNone, defaultVersion)
|
||||
require.ErrorIs(t, err, ErrRouteInvalidFormat)
|
||||
})
|
||||
|
||||
t.Run("ErrValidation if root route has no receiver", func(t *testing.T) {
|
||||
rev := getDefaultConfigRevision()
|
||||
sut, store, _ := createNotificationPolicyServiceSut()
|
||||
|
||||
@@ -673,7 +673,7 @@ func (st DBstore) ListAlertRules(ctx context.Context, query *ngmodels.ListAlertR
|
||||
}
|
||||
if query.TimeIntervalName != "" {
|
||||
if !slices.ContainsFunc(converted.NotificationSettings, func(settings ngmodels.NotificationSettings) bool {
|
||||
return slices.Contains(settings.MuteTimeIntervals, query.TimeIntervalName)
|
||||
return slices.Contains(settings.MuteTimeIntervals, query.TimeIntervalName) || slices.Contains(settings.ActiveTimeIntervals, query.TimeIntervalName)
|
||||
}) {
|
||||
continue
|
||||
}
|
||||
@@ -985,7 +985,7 @@ func (st DBstore) ListNotificationSettings(ctx context.Context, q ngmodels.ListN
|
||||
if q.ReceiverName != "" && q.ReceiverName != setting.Receiver { // currently, there can be only one setting. If in future there are more, we will return all settings of a rule that has a setting with receiver
|
||||
continue
|
||||
}
|
||||
if q.TimeIntervalName != "" && !slices.Contains(setting.MuteTimeIntervals, q.TimeIntervalName) {
|
||||
if q.TimeIntervalName != "" && !slices.Contains(setting.MuteTimeIntervals, q.TimeIntervalName) && !slices.Contains(setting.ActiveTimeIntervals, q.TimeIntervalName) {
|
||||
continue
|
||||
}
|
||||
ns = append(ns, setting)
|
||||
@@ -1157,6 +1157,11 @@ func (st DBstore) RenameTimeIntervalInNotificationSettings(
|
||||
r.NotificationSettings[idx].MuteTimeIntervals[mtIdx] = newTimeInterval
|
||||
}
|
||||
}
|
||||
for mtIdx := range r.NotificationSettings[idx].ActiveTimeIntervals {
|
||||
if r.NotificationSettings[idx].ActiveTimeIntervals[mtIdx] == oldTimeInterval {
|
||||
r.NotificationSettings[idx].ActiveTimeIntervals[mtIdx] = newTimeInterval
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updates = append(updates, ngmodels.UpdateRule{
|
||||
|
||||
@@ -907,7 +907,9 @@ func TestIntegrationAlertRulesNotificationSettings(t *testing.T) {
|
||||
gen = gen.With(gen.WithOrgID(1), gen.WithIntervalMatching(store.Cfg.BaseInterval))
|
||||
rules := gen.GenerateManyRef(3)
|
||||
receiveRules := gen.With(gen.WithNotificationSettingsGen(models.NotificationSettingsGen(models.NSMuts.WithReceiver(receiverName)))).GenerateManyRef(3)
|
||||
timeIntervalRules := gen.With(gen.WithNotificationSettingsGen(models.NotificationSettingsGen(models.NSMuts.WithMuteTimeIntervals(timeIntervalName)))).GenerateManyRef(3)
|
||||
mutetimeIntervalRules := gen.With(gen.WithNotificationSettingsGen(models.NotificationSettingsGen(models.NSMuts.WithMuteTimeIntervals(timeIntervalName)))).GenerateManyRef(3)
|
||||
activeTimeIntervalRules := gen.With(gen.WithNotificationSettingsGen(models.NotificationSettingsGen(models.NSMuts.WithActiveTimeIntervals(timeIntervalName)))).GenerateManyRef(3)
|
||||
timeIntervalRules := append(mutetimeIntervalRules, activeTimeIntervalRules...)
|
||||
noise := gen.With(gen.WithNotificationSettingsGen(models.NotificationSettingsGen(models.NSMuts.WithReceiver(timeIntervalName), models.NSMuts.WithMuteTimeIntervals(receiverName)))).GenerateManyRef(3)
|
||||
|
||||
deref := make([]models.AlertRule, 0, len(rules)+len(receiveRules)+len(timeIntervalRules)+len(noise))
|
||||
@@ -959,16 +961,21 @@ func TestIntegrationAlertRulesNotificationSettings(t *testing.T) {
|
||||
deref[i], deref[j] = deref[j], deref[i]
|
||||
})
|
||||
for _, rule := range deref {
|
||||
if len(rule.NotificationSettings) == 0 || rule.NotificationSettings[0].Receiver == "" || len(rule.NotificationSettings[0].MuteTimeIntervals) == 0 {
|
||||
if len(rule.NotificationSettings) == 0 || rule.NotificationSettings[0].Receiver == "" || len(rule.NotificationSettings[0].MuteTimeIntervals) == 0 || len(rule.NotificationSettings[0].ActiveTimeIntervals) == 0 {
|
||||
continue
|
||||
}
|
||||
if len(expected) > 0 {
|
||||
if rule.NotificationSettings[0].Receiver == receiver && slices.Contains(rule.NotificationSettings[0].MuteTimeIntervals, intervalName) {
|
||||
if rule.NotificationSettings[0].Receiver == receiver && (slices.Contains(rule.NotificationSettings[0].MuteTimeIntervals, intervalName) || slices.Contains(rule.NotificationSettings[0].ActiveTimeIntervals, intervalName)) {
|
||||
expected = append(expected, rule.GetKey())
|
||||
}
|
||||
} else {
|
||||
receiver = rule.NotificationSettings[0].Receiver
|
||||
intervalName = rule.NotificationSettings[0].MuteTimeIntervals[0]
|
||||
if len(rule.NotificationSettings[0].MuteTimeIntervals) > 0 {
|
||||
intervalName = rule.NotificationSettings[0].MuteTimeIntervals[0]
|
||||
}
|
||||
if len(rule.NotificationSettings[0].ActiveTimeIntervals) > 0 {
|
||||
intervalName = rule.NotificationSettings[0].ActiveTimeIntervals[0]
|
||||
}
|
||||
expected = append(expected, rule.GetKey())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,12 +203,13 @@ func (queryV1 *QueryV1) mapToModel() (models.AlertQuery, error) {
|
||||
}
|
||||
|
||||
type NotificationSettingsV1 struct {
|
||||
Receiver values.StringValue `json:"receiver" yaml:"receiver"`
|
||||
GroupBy []values.StringValue `json:"group_by,omitempty" yaml:"group_by"`
|
||||
GroupWait values.StringValue `json:"group_wait,omitempty" yaml:"group_wait"`
|
||||
GroupInterval values.StringValue `json:"group_interval,omitempty" yaml:"group_interval"`
|
||||
RepeatInterval values.StringValue `json:"repeat_interval,omitempty" yaml:"repeat_interval"`
|
||||
MuteTimeIntervals []values.StringValue `json:"mute_time_intervals,omitempty" yaml:"mute_time_intervals"`
|
||||
Receiver values.StringValue `json:"receiver" yaml:"receiver"`
|
||||
GroupBy []values.StringValue `json:"group_by,omitempty" yaml:"group_by"`
|
||||
GroupWait values.StringValue `json:"group_wait,omitempty" yaml:"group_wait"`
|
||||
GroupInterval values.StringValue `json:"group_interval,omitempty" yaml:"group_interval"`
|
||||
RepeatInterval values.StringValue `json:"repeat_interval,omitempty" yaml:"repeat_interval"`
|
||||
MuteTimeIntervals []values.StringValue `json:"mute_time_intervals,omitempty" yaml:"mute_time_intervals"`
|
||||
ActiveTimeIntervals []values.StringValue `json:"active_time_intervals,omitempty" yaml:"active_time_intervals"`
|
||||
}
|
||||
|
||||
func (nsV1 *NotificationSettingsV1) mapToModel() (models.NotificationSettings, error) {
|
||||
@@ -259,14 +260,25 @@ func (nsV1 *NotificationSettingsV1) mapToModel() (models.NotificationSettings, e
|
||||
mute = append(mute, value.Value())
|
||||
}
|
||||
}
|
||||
var active []string
|
||||
if len(nsV1.ActiveTimeIntervals) > 0 {
|
||||
active = make([]string, 0, len(nsV1.ActiveTimeIntervals))
|
||||
for _, value := range nsV1.ActiveTimeIntervals {
|
||||
if value.Value() == "" {
|
||||
continue
|
||||
}
|
||||
active = append(active, value.Value())
|
||||
}
|
||||
}
|
||||
|
||||
return models.NotificationSettings{
|
||||
Receiver: nsV1.Receiver.Value(),
|
||||
GroupBy: groupBy,
|
||||
GroupWait: gw,
|
||||
GroupInterval: gi,
|
||||
RepeatInterval: ri,
|
||||
MuteTimeIntervals: mute,
|
||||
Receiver: nsV1.Receiver.Value(),
|
||||
GroupBy: groupBy,
|
||||
GroupWait: gw,
|
||||
GroupInterval: gi,
|
||||
RepeatInterval: ri,
|
||||
MuteTimeIntervals: mute,
|
||||
ActiveTimeIntervals: active,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -212,20 +212,22 @@ func TestNotificationsSettingsV1MapToModel(t *testing.T) {
|
||||
{
|
||||
name: "Valid Input",
|
||||
input: NotificationSettingsV1{
|
||||
Receiver: stringToStringValue("test-receiver"),
|
||||
GroupBy: []values.StringValue{stringToStringValue("test-group_by")},
|
||||
GroupWait: stringToStringValue("1s"),
|
||||
GroupInterval: stringToStringValue("2s"),
|
||||
RepeatInterval: stringToStringValue("3s"),
|
||||
MuteTimeIntervals: []values.StringValue{stringToStringValue("test-mute")},
|
||||
Receiver: stringToStringValue("test-receiver"),
|
||||
GroupBy: []values.StringValue{stringToStringValue("test-group_by")},
|
||||
GroupWait: stringToStringValue("1s"),
|
||||
GroupInterval: stringToStringValue("2s"),
|
||||
RepeatInterval: stringToStringValue("3s"),
|
||||
MuteTimeIntervals: []values.StringValue{stringToStringValue("test-mute")},
|
||||
ActiveTimeIntervals: []values.StringValue{stringToStringValue("test-active")},
|
||||
},
|
||||
expected: models.NotificationSettings{
|
||||
Receiver: "test-receiver",
|
||||
GroupBy: []string{"test-group_by"},
|
||||
GroupWait: util.Pointer(model.Duration(1 * time.Second)),
|
||||
GroupInterval: util.Pointer(model.Duration(2 * time.Second)),
|
||||
RepeatInterval: util.Pointer(model.Duration(3 * time.Second)),
|
||||
MuteTimeIntervals: []string{"test-mute"},
|
||||
Receiver: "test-receiver",
|
||||
GroupBy: []string{"test-group_by"},
|
||||
GroupWait: util.Pointer(model.Duration(1 * time.Second)),
|
||||
GroupInterval: util.Pointer(model.Duration(2 * time.Second)),
|
||||
RepeatInterval: util.Pointer(model.Duration(3 * time.Second)),
|
||||
MuteTimeIntervals: []string{"test-mute"},
|
||||
ActiveTimeIntervals: []string{"test-active"},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -4415,16 +4415,27 @@ func TestIntegrationRuleNotificationSettings(t *testing.T) {
|
||||
t.Log(body)
|
||||
})
|
||||
|
||||
t.Run("create should fail if mute timing does not exist", func(t *testing.T) {
|
||||
var copyD testData
|
||||
err = json.Unmarshal(testDataRaw, ©D)
|
||||
group := copyD.RuleGroup
|
||||
ns := group.Rules[0].GrafanaManagedAlert.NotificationSettings
|
||||
ns.MuteTimeIntervals = []string{"random-time-interval"}
|
||||
t.Run("create should fail if time interval does not exist", func(t *testing.T) {
|
||||
t.Run("mute time interval", func(t *testing.T) {
|
||||
var copyD testData
|
||||
err = json.Unmarshal(testDataRaw, ©D)
|
||||
group := copyD.RuleGroup
|
||||
ns := group.Rules[0].GrafanaManagedAlert.NotificationSettings
|
||||
ns.MuteTimeIntervals = []string{"random-time-interval"}
|
||||
|
||||
_, status, body := apiClient.PostRulesGroupWithStatus(t, folder, &group, false)
|
||||
require.Equalf(t, http.StatusBadRequest, status, body)
|
||||
t.Log(body)
|
||||
_, status, body := apiClient.PostRulesGroupWithStatus(t, folder, &group, false)
|
||||
require.Equalf(t, http.StatusBadRequest, status, body)
|
||||
})
|
||||
t.Run("active time interval", func(t *testing.T) {
|
||||
var copyD testData
|
||||
err = json.Unmarshal(testDataRaw, ©D)
|
||||
group := copyD.RuleGroup
|
||||
ns := group.Rules[0].GrafanaManagedAlert.NotificationSettings
|
||||
ns.ActiveTimeIntervals = []string{"random-time-interval"}
|
||||
|
||||
_, status, body := apiClient.PostRulesGroupWithStatus(t, folder, &group, false)
|
||||
require.Equalf(t, http.StatusBadRequest, status, body)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("create should not fail if group_by is missing required labels but they should still be used", func(t *testing.T) {
|
||||
@@ -4483,6 +4494,7 @@ func TestIntegrationRuleNotificationSettings(t *testing.T) {
|
||||
assert.Nil(c, autogenRoute.GroupInterval)
|
||||
assert.Nil(c, autogenRoute.RepeatInterval)
|
||||
assert.Empty(c, autogenRoute.MuteTimeIntervals)
|
||||
assert.Empty(c, autogenRoute.ActiveTimeIntervals)
|
||||
assert.Empty(c, autogenRoute.GroupBy)
|
||||
if !canContinue {
|
||||
return
|
||||
@@ -4511,6 +4523,7 @@ func TestIntegrationRuleNotificationSettings(t *testing.T) {
|
||||
assert.Nil(c, receiverRoute.GroupInterval)
|
||||
assert.Nil(c, receiverRoute.RepeatInterval)
|
||||
assert.Empty(c, receiverRoute.MuteTimeIntervals)
|
||||
assert.Empty(c, receiverRoute.ActiveTimeIntervals)
|
||||
var groupBy []string
|
||||
for _, name := range receiverRoute.GroupBy {
|
||||
groupBy = append(groupBy, string(name))
|
||||
|
||||
@@ -538,13 +538,14 @@ func TestIntegrationDataConsistency(t *testing.T) {
|
||||
ensureMatcher(t, labels.MatchRegexp, "o", "1"),
|
||||
ensureMatcher(t, labels.MatchNotRegexp, "p", "1"),
|
||||
},
|
||||
Receiver: receiver,
|
||||
GroupByStr: []string{"test-789"},
|
||||
GroupWait: util.Pointer(model.Duration(2 * time.Minute)),
|
||||
GroupInterval: util.Pointer(model.Duration(5 * time.Minute)),
|
||||
RepeatInterval: util.Pointer(model.Duration(30 * time.Hour)),
|
||||
MuteTimeIntervals: []string{timeInterval},
|
||||
Continue: true,
|
||||
Receiver: receiver,
|
||||
GroupByStr: []string{"test-789"},
|
||||
GroupWait: util.Pointer(model.Duration(2 * time.Minute)),
|
||||
GroupInterval: util.Pointer(model.Duration(5 * time.Minute)),
|
||||
RepeatInterval: util.Pointer(model.Duration(30 * time.Hour)),
|
||||
MuteTimeIntervals: []string{timeInterval},
|
||||
ActiveTimeIntervals: []string{timeInterval},
|
||||
Continue: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -562,13 +563,14 @@ func TestIntegrationDataConsistency(t *testing.T) {
|
||||
}, tree.Spec.Defaults)
|
||||
assert.Len(t, tree.Spec.Routes, 1)
|
||||
assert.Equal(t, v0alpha1.Route{
|
||||
Continue: true,
|
||||
Receiver: util.Pointer(receiver),
|
||||
GroupBy: []string{"test-789"},
|
||||
GroupWait: util.Pointer("2m"),
|
||||
GroupInterval: util.Pointer("5m"),
|
||||
RepeatInterval: util.Pointer("1d6h"),
|
||||
MuteTimeIntervals: []string{timeInterval},
|
||||
Continue: true,
|
||||
Receiver: util.Pointer(receiver),
|
||||
GroupBy: []string{"test-789"},
|
||||
GroupWait: util.Pointer("2m"),
|
||||
GroupInterval: util.Pointer("5m"),
|
||||
RepeatInterval: util.Pointer("1d6h"),
|
||||
MuteTimeIntervals: []string{timeInterval},
|
||||
ActiveTimeIntervals: []string{timeInterval},
|
||||
Matchers: []v0alpha1.Matcher{
|
||||
{
|
||||
Label: "m",
|
||||
|
||||
@@ -3599,6 +3599,13 @@
|
||||
"continue"
|
||||
],
|
||||
"properties": {
|
||||
"active_time_intervals": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"continue": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
|
||||
Reference in New Issue
Block a user