Skip to content

Commit febff3f

Browse files
authored
Support alerting rules with only one of kql or timeframe fields (#886)
* Support alerting rules with only one of kql or timeframe fields * CHANGELOG.md * Fix tests * Fix alignment
1 parent 761cc7c commit febff3f

File tree

6 files changed

+67
-58
lines changed

6 files changed

+67
-58
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
- Use the auto-generated OAS schema from elastic/kibana for the Fleet API. ([#834](https://github.com/elastic/terraform-provider-elasticstack/issues/834))
55
- Support description in `elasticstack_elasticsearch_security_role` data sources. ([#884](https://github.com/elastic/terraform-provider-elasticstack/pull/884))
66
- Prevent spurious recreation of `elasticstack_fleet_agent_policy` resources due to 'changing' policy ids ([#885](https://github.com/elastic/terraform-provider-elasticstack/pull/885))
7+
- Support `elasticstack_kibana_alerting_rule` resources with only one of `kql` or `timeframe` attributes set ([#886](https://github.com/elastic/terraform-provider-elasticstack/pull/886))
78

89
## [0.11.11] - 2024-10-25
910

internal/clients/kibana/alerting.go

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,21 @@ func ruleResponseToModel(spaceID string, res *alerting.RuleResponseProperties) *
3939

4040
if !alerting.IsNil(action.AlertsFilter) {
4141
filter := unwrapOptionalField(action.AlertsFilter)
42-
timeframe := unwrapOptionalField(filter.Timeframe)
4342

44-
a.AlertsFilter = &models.ActionAlertsFilter{
45-
Kql: *filter.Query.Kql,
46-
Timeframe: models.AlertsFilterTimeframe{
43+
a.AlertsFilter = &models.ActionAlertsFilter{}
44+
45+
if filter.Query != nil {
46+
a.AlertsFilter.Kql = filter.Query.Kql
47+
}
48+
49+
if filter.Timeframe != nil {
50+
timeframe := unwrapOptionalField(filter.Timeframe)
51+
a.AlertsFilter.Timeframe = &models.AlertsFilterTimeframe{
4752
Days: timeframe.Days,
4853
Timezone: *timeframe.Timezone,
4954
HoursStart: *timeframe.Hours.Start,
5055
HoursEnd: *timeframe.Hours.End,
51-
},
56+
}
5257
}
5358
}
5459

@@ -116,21 +121,25 @@ func ruleActionsToActionsInner(ruleActions []models.AlertingRuleAction) []alerti
116121
}
117122

118123
if !alerting.IsNil(action.AlertsFilter) {
119-
timeframe := action.AlertsFilter.Timeframe
124+
filter := alerting.ActionsInnerAlertsFilter{}
120125

121-
filter := alerting.ActionsInnerAlertsFilter{
122-
Query: &alerting.ActionsInnerAlertsFilterQuery{
123-
Kql: &action.AlertsFilter.Kql,
126+
if action.AlertsFilter.Kql != nil {
127+
filter.Query = &alerting.ActionsInnerAlertsFilterQuery{
128+
Kql: action.AlertsFilter.Kql,
124129
Filters: []alerting.Filter{},
125-
},
126-
Timeframe: &alerting.ActionsInnerAlertsFilterTimeframe{
130+
}
131+
}
132+
133+
if action.AlertsFilter.Timeframe != nil {
134+
timeframe := action.AlertsFilter.Timeframe
135+
filter.Timeframe = &alerting.ActionsInnerAlertsFilterTimeframe{
127136
Timezone: &timeframe.Timezone,
128137
Days: timeframe.Days,
129138
Hours: &alerting.ActionsInnerAlertsFilterTimeframeHours{
130139
Start: &timeframe.HoursStart,
131140
End: &timeframe.HoursEnd,
132141
},
133-
},
142+
}
134143
}
135144

136145
actionToAppend.AlertsFilter = &filter

internal/clients/kibana/alerting_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ func Test_ruleResponseToModel(t *testing.T) {
147147
Throttle: utils.Pointer("10s"),
148148
},
149149
AlertsFilter: &models.ActionAlertsFilter{
150-
Kql: "foobar",
151-
Timeframe: models.AlertsFilterTimeframe{
150+
Kql: utils.Pointer("foobar"),
151+
Timeframe: &models.AlertsFilterTimeframe{
152152
Days: []int32{3, 5, 7},
153153
Timezone: "UTC+1",
154154
HoursStart: "00:00",

internal/kibana/alerting.go

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -367,24 +367,29 @@ func getActionsFromResourceData(d *schema.ResourceData, serverVersion *version.V
367367
return []models.AlertingRuleAction{}, diag.Errorf("actions.alerts_filter is only supported for Elasticsearch v8.9 or higher")
368368
}
369369

370-
resourceDays := d.Get(currentAction + ".alerts_filter.0.timeframe.0.days").([]interface{})
371-
days := []int32{}
370+
filter := models.ActionAlertsFilter{}
372371

373-
for _, a := range resourceDays {
374-
day := int32(a.(int))
375-
days = append(days, day)
376-
}
372+
if _, ok := d.GetOk(currentAction + ".alerts_filter.0.timeframe"); ok {
373+
374+
resourceDays := d.Get(currentAction + ".alerts_filter.0.timeframe.0.days").([]interface{})
375+
days := []int32{}
377376

378-
timeframe := models.AlertsFilterTimeframe{
379-
Days: days,
380-
Timezone: d.Get(currentAction + ".alerts_filter.0.timeframe.0.timezone").(string),
381-
HoursStart: d.Get(currentAction + ".alerts_filter.0.timeframe.0.hours_start").(string),
382-
HoursEnd: d.Get(currentAction + ".alerts_filter.0.timeframe.0.hours_end").(string),
377+
for _, a := range resourceDays {
378+
day := int32(a.(int))
379+
days = append(days, day)
380+
}
381+
382+
timeframe := models.AlertsFilterTimeframe{
383+
Days: days,
384+
Timezone: d.Get(currentAction + ".alerts_filter.0.timeframe.0.timezone").(string),
385+
HoursStart: d.Get(currentAction + ".alerts_filter.0.timeframe.0.hours_start").(string),
386+
HoursEnd: d.Get(currentAction + ".alerts_filter.0.timeframe.0.hours_end").(string),
387+
}
388+
filter.Timeframe = &timeframe
383389
}
384390

385-
filter := models.ActionAlertsFilter{
386-
Kql: d.Get(currentAction + ".alerts_filter.0.kql").(string),
387-
Timeframe: timeframe,
391+
if kql, ok := d.GetOk(currentAction + ".alerts_filter.0.kql"); ok {
392+
filter.Kql = utils.Pointer(kql.(string))
388393
}
389394

390395
a.AlertsFilter = &filter
@@ -547,18 +552,24 @@ func resourceRuleRead(ctx context.Context, d *schema.ResourceData, meta interfac
547552
alerts_filter := []interface{}{}
548553

549554
if action.AlertsFilter != nil {
550-
timeframe := []interface{}{}
551-
timeframe = append(timeframe, map[string]interface{}{
552-
"days": action.AlertsFilter.Timeframe.Days,
553-
"timezone": action.AlertsFilter.Timeframe.Timezone,
554-
"hours_start": action.AlertsFilter.Timeframe.HoursStart,
555-
"hours_end": action.AlertsFilter.Timeframe.HoursEnd,
556-
})
555+
filter := map[string]interface{}{}
556+
557+
if action.AlertsFilter.Timeframe != nil {
558+
timeframe := []interface{}{}
559+
timeframe = append(timeframe, map[string]interface{}{
560+
"days": action.AlertsFilter.Timeframe.Days,
561+
"timezone": action.AlertsFilter.Timeframe.Timezone,
562+
"hours_start": action.AlertsFilter.Timeframe.HoursStart,
563+
"hours_end": action.AlertsFilter.Timeframe.HoursEnd,
564+
})
565+
filter["timeframe"] = timeframe
566+
}
557567

558-
alerts_filter = append(alerts_filter, map[string]interface{}{
559-
"kql": action.AlertsFilter.Kql,
560-
"timeframe": timeframe,
561-
})
568+
if action.AlertsFilter.Kql != nil {
569+
filter["kql"] = action.AlertsFilter.Kql
570+
}
571+
572+
alerts_filter = append(alerts_filter, filter)
562573
} else {
563574
alerts_filter = nil
564575
}

internal/kibana/alerting_test.go

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func TestAccResourceAlertingRule(t *testing.T) {
112112
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.frequency.0.summary", "true"),
113113
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.frequency.0.notify_when", "onActionGroupChange"),
114114
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.frequency.0.throttle", "10m"),
115-
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.alerts_filter.0.kql", `kibana.alert.action_group: "slo.burnRate.alert" OR kibana.alert.action_group : "slo.burnRate.high"`),
115+
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.alerts_filter.0.kql", ""),
116116
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.alerts_filter.0.timeframe.0.days.0", "1"),
117117
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.alerts_filter.0.timeframe.0.days.1", "2"),
118118
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.alerts_filter.0.timeframe.0.days.2", "3"),
@@ -138,10 +138,7 @@ func TestAccResourceAlertingRule(t *testing.T) {
138138
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.frequency.0.notify_when", "onActionGroupChange"),
139139
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.frequency.0.throttle", "10m"),
140140
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.alerts_filter.0.kql", `kibana.alert.action_group: "slo.burnRate.alert"`),
141-
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.alerts_filter.0.timeframe.0.days.0", "7"),
142-
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.alerts_filter.0.timeframe.0.timezone", "Pacific/Honolulu"),
143-
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.alerts_filter.0.timeframe.0.hours_start", "02:00"),
144-
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.alerts_filter.0.timeframe.0.hours_end", "03:00"),
141+
resource.TestCheckResourceAttr("elasticstack_kibana_alerting_rule.test_rule", "actions.0.alerts_filter.0.timeframe.#", "0"),
145142
),
146143
},
147144
{
@@ -428,13 +425,11 @@ resource "elasticstack_kibana_alerting_rule" "test_rule" {
428425
}
429426
430427
alerts_filter {
431-
kql = "kibana.alert.action_group: \"slo.burnRate.alert\" OR kibana.alert.action_group : \"slo.burnRate.high\""
432-
433428
timeframe {
434429
days = [1,2,3]
435-
timezone = "Africa/Accra"
436-
hours_start = "01:00"
437-
hours_end = "07:00"
430+
timezone = "Africa/Accra"
431+
hours_start = "01:00"
432+
hours_end = "07:00"
438433
}
439434
}
440435
}
@@ -503,13 +498,6 @@ resource "elasticstack_kibana_alerting_rule" "test_rule" {
503498
504499
alerts_filter {
505500
kql = "kibana.alert.action_group: \"slo.burnRate.alert\""
506-
507-
timeframe {
508-
days = [7]
509-
timezone = "Pacific/Honolulu"
510-
hours_start = "02:00"
511-
hours_end = "03:00"
512-
}
513501
}
514502
}
515503
}

internal/models/alert_rule.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ type ActionFrequency struct {
4747
}
4848

4949
type ActionAlertsFilter struct {
50-
Kql string
51-
Timeframe AlertsFilterTimeframe
50+
Kql *string
51+
Timeframe *AlertsFilterTimeframe
5252
}
5353

5454
type AlertsFilterTimeframe struct {

0 commit comments

Comments
 (0)