Skip to content

Commit 9d8c7bd

Browse files
authored
Add support for the alerts_filter param in the Create Rule API (#774)
* Add support for alerts_filter in alerting resource. * docs * updated the tests * Updated the changelog.
1 parent c62d386 commit 9d8c7bd

File tree

8 files changed

+664
-28
lines changed

8 files changed

+664
-28
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
## [Unreleased]
22

3+
- Add the `alerts_filter` field to the `actions` in the Create Rule API ([#774](https://github.com/elastic/terraform-provider-elasticstack/pull/774))
34
- Add the `alert_delay` field to the Create Rule API ([#715](https://github.com/elastic/terraform-provider-elasticstack/pull/715))
45
- Add support for data_stream `lifecycle` template settings ([#724](https://github.com/elastic/terraform-provider-elasticstack/pull/724))
56
- Fix a provider panic when `elasticstack_kibana_action_connector` reads a non-existant connector ([#729](https://github.com/elastic/terraform-provider-elasticstack/pull/729))
67
- Add support for `remote_indicies` to `elasticstack_elasticsearch_security_role` & `elasticstack_kibana_security_role` (#723)[https://github.com/elastic/terraform-provider-elasticstack/pull/723]
78
- Fix error handling in `elasticstack_kibana_import_saved_objects` ([#738](https://github.com/elastic/terraform-provider-elasticstack/pull/738))
8-
- Remove `space_id` parameter from private locations to fix inconsistent state for `elasticstack_kibana_synthetics_private_location` `space_id` ([#733](https://github.com/elastic/terraform-provider-elasticstack/pull/733))
9+
- Remove `space_id` parameter from private locations to fix inconsistent state for `elasticstack_kibana_synthetics_private_location` `space_id` ([#733](https://github.com/elastic/terraform-provider-elasticstack/pull/733))
910
- Add the `Frequency` field to the Create Rule API ([#753](https://github.com/elastic/terraform-provider-elasticstack/pull/753))
1011
- Prevent a provider panic when the repository referenced in an `elasticstack_elasticsearch_snapshot_repository` does not exist ([#758](https://github.com/elastic/terraform-provider-elasticstack/pull/758))
1112
- Add support for `remote_indicies` to `elasticstack_elasticsearch_security_api_key` (#766)[https://github.com/elastic/terraform-provider-elasticstack/pull/766]

docs/resources/kibana_alerting_rule.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,30 @@ Required:
8686

8787
Optional:
8888

89+
- `alerts_filter` (Block List, Max: 1) Conditions that affect whether the action runs. If you specify multiple conditions, all conditions must be met for the action to run. For example, if an alert occurs within the specified time frame and matches the query, the action runs. (see [below for nested schema](#nestedblock--actions--alerts_filter))
8990
- `frequency` (Block List, Max: 1) The properties that affect how often actions are generated. If the rule type supports setting summary to true, the action can be a summary of alerts at the specified notification interval. Otherwise, an action runs for each alert at the specified notification interval. NOTE: You cannot specify these parameters when `notify_when` or `throttle` are defined at the rule level. (see [below for nested schema](#nestedblock--actions--frequency))
9091
- `group` (String) The group name, which affects when the action runs (for example, when the threshold is met or when the alert is recovered). Each rule type has a list of valid action group names.
9192

93+
<a id="nestedblock--actions--alerts_filter"></a>
94+
### Nested Schema for `actions.alerts_filter`
95+
96+
Optional:
97+
98+
- `kql` (String) Defines a query filter that determines whether the action runs. Written in Kibana Query Language (KQL).
99+
- `timeframe` (Block List, Max: 1) Defines a period that limits whether the action runs. (see [below for nested schema](#nestedblock--actions--alerts_filter--timeframe))
100+
101+
<a id="nestedblock--actions--alerts_filter--timeframe"></a>
102+
### Nested Schema for `actions.alerts_filter.timeframe`
103+
104+
Required:
105+
106+
- `days` (List of Number) Defines the days of the week that the action can run, represented as an array of numbers. For example, 1 represents Monday. An empty array is equivalent to specifying all the days of the week.
107+
- `hours_end` (String) Defines the range of time in a day that the action can run. The end of the time frame in 24-hour notation (hh:mm).
108+
- `hours_start` (String) Defines the range of time in a day that the action can run. The start of the time frame in 24-hour notation (hh:mm).
109+
- `timezone` (String) The ISO time zone for the hours values. Values such as UTC and UTC+1 also work but lack built-in daylight savings time support and are not recommended.
110+
111+
112+
92113
<a id="nestedblock--actions--frequency"></a>
93114
### Nested Schema for `actions.frequency`
94115

internal/clients/kibana/alerting.go

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,28 @@ func ruleResponseToModel(spaceID string, res *alerting.RuleResponseProperties) *
3030
if !alerting.IsNil(action.Frequency) {
3131
frequency := unwrapOptionalField(action.Frequency)
3232

33-
a.Frequency = &models.AlertingRuleActionFrequency{
33+
a.Frequency = &models.ActionFrequency{
3434
Summary: frequency.Summary,
3535
NotifyWhen: (string)(frequency.NotifyWhen),
3636
Throttle: frequency.Throttle.Get(),
3737
}
3838
}
3939

40+
if !alerting.IsNil(action.AlertsFilter) {
41+
filter := unwrapOptionalField(action.AlertsFilter)
42+
timeframe := unwrapOptionalField(filter.Timeframe)
43+
44+
a.AlertsFilter = &models.ActionAlertsFilter{
45+
Kql: *filter.Query.Kql,
46+
Timeframe: models.AlertsFilterTimeframe{
47+
Days: timeframe.Days,
48+
Timezone: *timeframe.Timezone,
49+
HoursStart: *timeframe.Hours.Start,
50+
HoursEnd: *timeframe.Hours.End,
51+
},
52+
}
53+
}
54+
4055
actions = append(actions, a)
4156
}
4257

@@ -100,6 +115,27 @@ func ruleActionsToActionsInner(ruleActions []models.AlertingRuleAction) []alerti
100115
actionToAppend.Frequency = &frequency
101116
}
102117

118+
if !alerting.IsNil(action.AlertsFilter) {
119+
timeframe := action.AlertsFilter.Timeframe
120+
121+
filter := alerting.ActionsInnerAlertsFilter{
122+
Query: &alerting.ActionsInnerAlertsFilterQuery{
123+
Kql: &action.AlertsFilter.Kql,
124+
Filters: []alerting.Filter{},
125+
},
126+
Timeframe: &alerting.ActionsInnerAlertsFilterTimeframe{
127+
Timezone: &timeframe.Timezone,
128+
Days: timeframe.Days,
129+
Hours: &alerting.ActionsInnerAlertsFilterTimeframeHours{
130+
Start: &timeframe.HoursStart,
131+
End: &timeframe.HoursEnd,
132+
},
133+
},
134+
}
135+
136+
actionToAppend.AlertsFilter = &filter
137+
}
138+
103139
actions = append(actions, actionToAppend)
104140
}
105141
return actions

internal/clients/kibana/alerting_test.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ func Test_ruleResponseToModel(t *testing.T) {
7777
NotifyWhen: "onThrottleInterval",
7878
Throttle: *alerting.NewNullableString(utils.Pointer("10s")),
7979
}),
80+
AlertsFilter: utils.Pointer(alerting.ActionsInnerAlertsFilter{
81+
Query: &alerting.ActionsInnerAlertsFilterQuery{
82+
Kql: utils.Pointer("foobar"),
83+
},
84+
Timeframe: &alerting.ActionsInnerAlertsFilterTimeframe{
85+
Days: []int32{3, 5, 7},
86+
Timezone: utils.Pointer("UTC+1"),
87+
Hours: &alerting.ActionsInnerAlertsFilterTimeframeHours{
88+
Start: utils.Pointer("00:00"),
89+
End: utils.Pointer("08:00"),
90+
},
91+
},
92+
}),
8093
},
8194
{
8295
Group: "group-2",
@@ -128,17 +141,26 @@ func Test_ruleResponseToModel(t *testing.T) {
128141
Group: "group-1",
129142
ID: "id",
130143
Params: map[string]interface{}{},
131-
Frequency: &models.AlertingRuleActionFrequency{
144+
Frequency: &models.ActionFrequency{
132145
Summary: true,
133146
NotifyWhen: "onThrottleInterval",
134147
Throttle: utils.Pointer("10s"),
135148
},
149+
AlertsFilter: &models.ActionAlertsFilter{
150+
Kql: "foobar",
151+
Timeframe: models.AlertsFilterTimeframe{
152+
Days: []int32{3, 5, 7},
153+
Timezone: "UTC+1",
154+
HoursStart: "00:00",
155+
HoursEnd: "08:00",
156+
},
157+
},
136158
},
137159
{
138160
Group: "group-2",
139161
ID: "id",
140162
Params: map[string]interface{}{},
141-
Frequency: &models.AlertingRuleActionFrequency{
163+
Frequency: &models.ActionFrequency{
142164
Summary: true,
143165
NotifyWhen: "onActionGroupChange",
144166
},

internal/kibana/alerting.go

Lines changed: 108 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ import (
1616
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1717
)
1818

19-
var alertDelayMinSupportedVersion = version.Must(version.NewVersion("8.13.0"))
20-
2119
// when notify_when and throttle became optional
2220
var frequencyMinSupportedVersion = version.Must(version.NewVersion("8.6.0"))
21+
var alertsFilterMinSupportedVersion = version.Must(version.NewVersion("8.9.0"))
22+
var alertDelayMinSupportedVersion = version.Must(version.NewVersion("8.13.0"))
2323

2424
func ResourceAlertingRule() *schema.Resource {
2525
apikeySchema := map[string]*schema.Schema{
@@ -125,6 +125,59 @@ func ResourceAlertingRule() *schema.Resource {
125125
},
126126
},
127127
},
128+
"alerts_filter": {
129+
Description: "Conditions that affect whether the action runs. If you specify multiple conditions, all conditions must be met for the action to run. For example, if an alert occurs within the specified time frame and matches the query, the action runs.",
130+
Type: schema.TypeList,
131+
MinItems: 0,
132+
MaxItems: 1,
133+
Optional: true,
134+
Elem: &schema.Resource{
135+
Schema: map[string]*schema.Schema{
136+
"kql": {
137+
Description: "Defines a query filter that determines whether the action runs. Written in Kibana Query Language (KQL).",
138+
Type: schema.TypeString,
139+
Optional: true,
140+
},
141+
"timeframe": {
142+
Description: "Defines a period that limits whether the action runs.",
143+
Type: schema.TypeList,
144+
MinItems: 0,
145+
MaxItems: 1,
146+
Optional: true,
147+
Elem: &schema.Resource{
148+
Schema: map[string]*schema.Schema{
149+
"days": {
150+
Description: "Defines the days of the week that the action can run, represented as an array of numbers. For example, 1 represents Monday. An empty array is equivalent to specifying all the days of the week.",
151+
Type: schema.TypeList,
152+
Required: true,
153+
Elem: &schema.Schema{
154+
Type: schema.TypeInt,
155+
ValidateFunc: validation.IntBetween(1, 7),
156+
},
157+
},
158+
"timezone": {
159+
Description: "The ISO time zone for the hours values. Values such as UTC and UTC+1 also work but lack built-in daylight savings time support and are not recommended.",
160+
Type: schema.TypeString,
161+
Required: true,
162+
},
163+
"hours_start": {
164+
Description: "Defines the range of time in a day that the action can run. The start of the time frame in 24-hour notation (hh:mm).",
165+
Type: schema.TypeString,
166+
Required: true,
167+
ValidateFunc: utils.StringIsHours,
168+
},
169+
"hours_end": {
170+
Description: "Defines the range of time in a day that the action can run. The end of the time frame in 24-hour notation (hh:mm).",
171+
Type: schema.TypeString,
172+
Required: true,
173+
ValidateFunc: utils.StringIsHours,
174+
},
175+
},
176+
},
177+
},
178+
},
179+
},
180+
},
128181
},
129182
},
130183
},
@@ -288,7 +341,7 @@ func getActionsFromResourceData(d *schema.ResourceData, serverVersion *version.V
288341
return []models.AlertingRuleAction{}, diag.Errorf("actions.frequency is only supported for Elasticsearch v8.6 or higher")
289342
}
290343

291-
frequency := models.AlertingRuleActionFrequency{
344+
frequency := models.ActionFrequency{
292345
Summary: d.Get(currentAction + ".frequency.0.summary").(bool),
293346
NotifyWhen: d.Get(currentAction + ".frequency.0.notify_when").(string),
294347
}
@@ -300,6 +353,34 @@ func getActionsFromResourceData(d *schema.ResourceData, serverVersion *version.V
300353
a.Frequency = &frequency
301354
}
302355

356+
if _, ok := d.GetOk(currentAction + ".alerts_filter"); ok {
357+
if serverVersion.LessThan(alertsFilterMinSupportedVersion) {
358+
return []models.AlertingRuleAction{}, diag.Errorf("actions.alerts_filter is only supported for Elasticsearch v8.9 or higher")
359+
}
360+
361+
resourceDays := d.Get(currentAction + ".alerts_filter.0.timeframe.0.days").([]interface{})
362+
days := []int32{}
363+
364+
for _, a := range resourceDays {
365+
day := int32(a.(int))
366+
days = append(days, day)
367+
}
368+
369+
timeframe := models.AlertsFilterTimeframe{
370+
Days: days,
371+
Timezone: d.Get(currentAction + ".alerts_filter.0.timeframe.0.timezone").(string),
372+
HoursStart: d.Get(currentAction + ".alerts_filter.0.timeframe.0.hours_start").(string),
373+
HoursEnd: d.Get(currentAction + ".alerts_filter.0.timeframe.0.hours_end").(string),
374+
}
375+
376+
filter := models.ActionAlertsFilter{
377+
Kql: d.Get(currentAction + ".alerts_filter.0.kql").(string),
378+
Timeframe: timeframe,
379+
}
380+
381+
a.AlertsFilter = &filter
382+
}
383+
303384
actions = append(actions, a)
304385
}
305386
}
@@ -454,11 +535,31 @@ func resourceRuleRead(ctx context.Context, d *schema.ResourceData, meta interfac
454535
frequency = nil
455536
}
456537

538+
alerts_filter := []interface{}{}
539+
540+
if action.AlertsFilter != nil {
541+
timeframe := []interface{}{}
542+
timeframe = append(timeframe, map[string]interface{}{
543+
"days": action.AlertsFilter.Timeframe.Days,
544+
"timezone": action.AlertsFilter.Timeframe.Timezone,
545+
"hours_start": action.AlertsFilter.Timeframe.HoursStart,
546+
"hours_end": action.AlertsFilter.Timeframe.HoursEnd,
547+
})
548+
549+
alerts_filter = append(alerts_filter, map[string]interface{}{
550+
"kql": action.AlertsFilter.Kql,
551+
"timeframe": timeframe,
552+
})
553+
} else {
554+
alerts_filter = nil
555+
}
556+
457557
actions = append(actions, map[string]interface{}{
458-
"group": action.Group,
459-
"id": action.ID,
460-
"params": string(params),
461-
"frequency": frequency,
558+
"group": action.Group,
559+
"id": action.ID,
560+
"params": string(params),
561+
"frequency": frequency,
562+
"alerts_filter": alerts_filter,
462563
})
463564
}
464565

0 commit comments

Comments
 (0)