diff --git a/README.md b/README.md index f6d6a9a..6f15c88 100644 --- a/README.md +++ b/README.md @@ -235,10 +235,10 @@ No resources. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [alert\_interval\_seconds](#input\_alert\_interval\_seconds) | The interval, in seconds, at which all rules in the group are evaluated. If a group contains many rules, the rules are evaluated sequentially. | `number` | `10` | no | -| [alert\_rules](#input\_alert\_rules) | This variable describes alert folders, groups and rules. |
list(object({
name = string # The name of the alert rule
no_data_state = optional(string, "NoData") # Describes what state to enter when the rule's query returns No Data
exec_err_state = optional(string, "Error") # Describes what state to enter when the rule's query is invalid and the rule cannot be executed
summary = optional(string, "") # Rule annotation as a summary
priority = optional(string, "P2") # Rule priority level: P2 is for non-critical alerts, P1 will be set for critical alerts
folder_name = optional(string, "Main Alerts") # Grafana folder name in which the rule will be created
datasource = string # Name of the datasource used for the alert
expr = optional(string, null) # Full expression for the alert
metric_name = optional(string, "") # Prometheus metric name which queries the data for the alert
metric_function = optional(string, "") # Prometheus function used with metric for queries, like rate, sum etc.
metric_interval = optional(string, "") # The time interval with using functions like rate
settings_mode = optional(string, "replaceNN") # The mode used in B block, possible values are Strict, replaceNN, dropNN
settings_replaceWith = optional(number, 0) # The value by which NaN results of the query will be replaced
filters = optional(any, {}) # Filters object to identify each service for alerting
function = optional(string, "mean") # One of Reduce functions which will be used in B block for alerting
equation = string # The equation in the math expression which compares B blocks value with a number and generates an alert if needed. Possible values: gt, lt, gte, lte, e
threshold = number # The value against which B blocks are compared in the math expression
}))
| `[]` | no | +| [alert\_rules](#input\_alert\_rules) | This variable describes alert folders, groups and rules. |
list(object({
name = string # The name of the alert rule
no_data_state = optional(string, "NoData") # Describes what state to enter when the rule's query returns No Data
exec_err_state = optional(string, "Error") # Describes what state to enter when the rule's query is invalid and the rule cannot be executed
summary = optional(string, "") # Rule annotation as a summary
labels = optional(map(any), { "priorityLow" : "true" })
folder_name = optional(string, "Main Alerts") # Grafana folder name in which the rule will be created
datasource = string # Name of the datasource used for the alert
expr = optional(string, null) # Full expression for the alert
metric_name = optional(string, "") # Prometheus metric name which queries the data for the alert
metric_function = optional(string, "") # Prometheus function used with metric for queries, like rate, sum etc.
metric_interval = optional(string, "") # The time interval with using functions like rate
settings_mode = optional(string, "replaceNN") # The mode used in B block, possible values are Strict, replaceNN, dropNN
settings_replaceWith = optional(number, 0) # The value by which NaN results of the query will be replaced
filters = optional(any, {}) # Filters object to identify each service for alerting
function = optional(string, "mean") # One of Reduce functions which will be used in B block for alerting
equation = string # The equation in the math expression which compares B blocks value with a number and generates an alert if needed. Possible values: gt, lt, gte, lte, e
threshold = number # The value against which B blocks are compared in the math expression
}))
| `[]` | no | | [application\_dashboard](#input\_application\_dashboard) | Dashboard for monitoring applications |
object({
rows = optional(any, [])
data_source = object({ # global/default datasource, TODO: create datasource inside the module
uid = string
type = optional(string, "prometheus")
})
variables = optional(list(object({ # Allows to define variables to be used in dashboard
name = string
type = optional(string, "custom")
hide = optional(number, 0)
includeAll = optional(bool, false)
multi = optional(bool, false)
query = optional(string, "")
queryValue = optional(string, "")
skipUrlSync = optional(bool, false)
options = optional(list(object({
selected = optional(bool, false)
value = string
text = optional(string, null)
})), [])
})), [])
})
|
{
"data_source": null,
"rows": [],
"variables": []
}
| no | | [name](#input\_name) | Dashboard name | `string` | n/a | yes | -| [notifications](#input\_notifications) | Represents the configuration options for Grafana notification policies. |
object({
contact_point = optional(string, "Slack") # The default contact point to route all unmatched notifications to.
group_by = optional(list(string), ["grafana_folder", "alertname"]) # A list of alert labels to group alerts into notifications by.
group_interval = optional(string, "5m") # Minimum time interval between two notifications for the same group.
repeat_interval = optional(string, "4h") # Minimum time interval for re-sending a notification if an alert is still firing.

policy = optional(object({
contact_point = optional(string, null) # The contact point to route notifications that match this rule to.
continue = optional(bool, false) # Whether to continue matching subsequent rules if an alert matches the current rule. Otherwise, the rule will be 'consumed' by the first policy to match it.
group_by = optional(list(string), [])
mute_timings = optional(list(string), []) # A list of mute timing names to apply to alerts that match this policy.

matcher = optional(object({
label = optional(string, "priority") # The name of the label to match against.
match = optional(string, "=") # The operator to apply when matching values of the given label. Allowed operators are = for equality, != for negated equality, =~ for regex equality, and !~ for negated regex equality.
value = optional(string, "P1") # The label value to match against.
}))
}))
})
| `{}` | no | +| [notifications](#input\_notifications) | Represents the configuration options for Grafana notification policies. |
object({
contact_point = optional(string, "Slack") # The default contact point to route all unmatched notifications to.
group_by = optional(list(string), ["..."]) # A list of alert labels to group alerts into notifications by.
group_interval = optional(string, "5m") # Minimum time interval between two notifications for the same group.
repeat_interval = optional(string, "4h") # Minimum time interval for re-sending a notification if an alert is still firing.

policies = optional(list(object({
contact_point = optional(string, null) # The contact point to route notifications that match this rule to.
continue = optional(bool, false) # Whether to continue matching subsequent rules if an alert matches the current rule. Otherwise, the rule will be 'consumed' by the first policy to match it.
group_by = optional(list(string), ["..."])
mute_timings = optional(list(string), []) # A list of mute timing names to apply to alerts that match this policy.

matchers = optional(list(object({
label = optional(string, "priority") # The name of the label to match against.
match = optional(string, "=") # The operator to apply when matching values of the given label. Allowed operators are = for equality, != for negated equality, =~ for regex equality, and !~ for negated regex equality.
value = optional(string, "P1") # The label value to match against.
})), [])
})), [])
})
| `{}` | no | | [opsgenie\_endpoints](#input\_opsgenie\_endpoints) | OpsGenie contact points list. |
list(object({
name = string # The name of the contact point.
api_key = string # The OpsGenie API key to use.
auto_close = optional(bool, false) # Whether to auto-close alerts in OpsGenie when they resolve in the Alertmanager.
message = optional(string, "") # The templated content of the message.
api_url = optional(string, "https://api.opsgenie.com/v2/alerts") # Allows customization of the OpsGenie API URL.
disable_resolve_message = optional(bool, false) # Whether to disable sending resolve messages.
}))
| `[]` | no | | [slack\_endpoints](#input\_slack\_endpoints) | Slack contact points list. |
list(object({
name = string # The name of the contact point.
endpoint_url = optional(string, "https://slack.com/api/chat.postMessage") # Use this to override the Slack API endpoint URL to send requests to.
icon_emoji = optional(string, "") # The name of a Slack workspace emoji to use as the bot icon.
icon_url = optional(string, "") # A URL of an image to use as the bot icon.
recipient = optional(string, null) # Channel, private group, or IM channel (can be an encoded ID or a name) to send messages to.
text = optional(string, "") # Templated content of the message.
title = optional(string, "") # Templated title of the message.
token = optional(string, "") # A Slack API token,for sending messages directly without the webhook method.
webhook_url = optional(string, "") # A Slack webhook URL,for sending messages via the webhook method.
username = optional(string, "") # Username for the bot to use.
disable_resolve_message = optional(bool, false) # Whether to disable sending resolve messages.
}))
| `[]` | no | diff --git a/main.tf b/main.tf index d555099..0290688 100644 --- a/main.tf +++ b/main.tf @@ -8,6 +8,8 @@ module "alerts" { module "contact_points" { source = "./modules/contact-points" + count = length(var.alert_rules) != 0 ? 1 : 0 + slack_endpoints = var.slack_endpoints opsgenie_endpoints = var.opsgenie_endpoints } @@ -15,5 +17,7 @@ module "contact_points" { module "notifications" { source = "./modules/notifications" + count = length(var.alert_rules) != 0 ? 1 : 0 + notifications = var.notifications } diff --git a/modules/alerts/README.md b/modules/alerts/README.md index 19e2cc0..728cd6b 100644 --- a/modules/alerts/README.md +++ b/modules/alerts/README.md @@ -49,7 +49,7 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [alert\_interval\_seconds](#input\_alert\_interval\_seconds) | The interval, in seconds, at which all rules in the group are evaluated. If a group contains many rules, the rules are evaluated sequentially. | `number` | `10` | no | -| [alert\_rules](#input\_alert\_rules) | This varibale describes alert folders, groups and rules. |
list(object({
name = string # The name of the alert rule
no_data_state = optional(string, "NoData") # Describes what state to enter when the rule's query returns No Data
exec_err_state = optional(string, "Error") # Describes what state to enter when the rule's query is invalid and the rule cannot be executed
summary = optional(string, "") # Rule annotation as a summary
priority = optional(string, "P2") # Rule priority level: P2 is for non-critical alerts, P1 will be set for critical alerts
folder_name = optional(string, "Main Alerts") # Grafana folder name in which the rule will be created
datasource = string # Name of the datasource used for the alert
expr = optional(string, null) # Full expression for the alert
metric_name = optional(string, "") # Prometheus metric name which queries the data for the alert
metric_function = optional(string, "") # Prometheus function used with metric for queries, like rate, sum etc.
metric_interval = optional(string, "") # The time interval with using functions like rate
settings_mode = optional(string, "replaceNN") # The mode used in B block, possible values are Strict, replaceNN, dropNN
settings_replaceWith = optional(number, 0) # The value by which NaN results of the query will be replaced
filters = optional(any, {}) # Filters object to identify each service for alerting
function = optional(string, "mean") # One of Reduce functions which will be used in B block for alerting
equation = string # The equation in the math expression which compares B blocks value with a number and generates an alert if needed. Possible values: gt, lt, gte, lte, e
threshold = number # The value against which B blocks are compared in the math expression
}))
| `[]` | no | +| [alert\_rules](#input\_alert\_rules) | This varibale describes alert folders, groups and rules. |
list(object({
name = string # The name of the alert rule
no_data_state = optional(string, "NoData") # Describes what state to enter when the rule's query returns No Data
exec_err_state = optional(string, "Error") # Describes what state to enter when the rule's query is invalid and the rule cannot be executed
summary = optional(string, "") # Rule annotation as a summary
labels = optional(map(any), { "priorityLow" : "true" }) # Labels help to define where to send each alert
folder_name = optional(string, "Main Alerts") # Grafana folder name in which the rule will be created
datasource = string # Name of the datasource used for the alert
expr = optional(string, null) # Full expression for the alert
metric_name = optional(string, "") # Prometheus metric name which queries the data for the alert
metric_function = optional(string, "") # Prometheus function used with metric for queries, like rate, sum etc.
metric_interval = optional(string, "") # The time interval with using functions like rate
settings_mode = optional(string, "replaceNN") # The mode used in B block, possible values are Strict, replaceNN, dropNN
settings_replaceWith = optional(number, 0) # The value by which NaN results of the query will be replaced
filters = optional(any, {}) # Filters object to identify each service for alerting
function = optional(string, "mean") # One of Reduce functions which will be used in B block for alerting
equation = string # The equation in the math expression which compares B blocks value with a number and generates an alert if needed. Possible values: gt, lt, gte, lte, e
threshold = number # The value against which B blocks are compared in the math expression
}))
| `[]` | no | ## Outputs diff --git a/modules/alerts/main.tf b/modules/alerts/main.tf index b92ef31..d0291d2 100644 --- a/modules/alerts/main.tf +++ b/modules/alerts/main.tf @@ -36,9 +36,9 @@ resource "grafana_rule_group" "alert_rule" { "Managed By" = "Terraform" "Summary" = lookup(rule.value, "summary", rule.value.name) } - labels = { - "priority" = lookup(rule.value, "priority", "P2") - } + labels = lookup(rule.value, "labels", { + "priorityLow" : "true" + }) is_paused = false data { ref_id = "A" diff --git a/modules/alerts/variables.tf b/modules/alerts/variables.tf index 3bc5d74..08806d2 100644 --- a/modules/alerts/variables.tf +++ b/modules/alerts/variables.tf @@ -6,23 +6,23 @@ variable "alert_interval_seconds" { variable "alert_rules" { type = list(object({ - name = string # The name of the alert rule - no_data_state = optional(string, "NoData") # Describes what state to enter when the rule's query returns No Data - exec_err_state = optional(string, "Error") # Describes what state to enter when the rule's query is invalid and the rule cannot be executed - summary = optional(string, "") # Rule annotation as a summary - priority = optional(string, "P2") # Rule priority level: P2 is for non-critical alerts, P1 will be set for critical alerts - folder_name = optional(string, "Main Alerts") # Grafana folder name in which the rule will be created - datasource = string # Name of the datasource used for the alert - expr = optional(string, null) # Full expression for the alert - metric_name = optional(string, "") # Prometheus metric name which queries the data for the alert - metric_function = optional(string, "") # Prometheus function used with metric for queries, like rate, sum etc. - metric_interval = optional(string, "") # The time interval with using functions like rate - settings_mode = optional(string, "replaceNN") # The mode used in B block, possible values are Strict, replaceNN, dropNN - settings_replaceWith = optional(number, 0) # The value by which NaN results of the query will be replaced - filters = optional(any, {}) # Filters object to identify each service for alerting - function = optional(string, "mean") # One of Reduce functions which will be used in B block for alerting - equation = string # The equation in the math expression which compares B blocks value with a number and generates an alert if needed. Possible values: gt, lt, gte, lte, e - threshold = number # The value against which B blocks are compared in the math expression + name = string # The name of the alert rule + no_data_state = optional(string, "NoData") # Describes what state to enter when the rule's query returns No Data + exec_err_state = optional(string, "Error") # Describes what state to enter when the rule's query is invalid and the rule cannot be executed + summary = optional(string, "") # Rule annotation as a summary + labels = optional(map(any), { "priorityLow" : "true" }) # Labels help to define where to send each alert + folder_name = optional(string, "Main Alerts") # Grafana folder name in which the rule will be created + datasource = string # Name of the datasource used for the alert + expr = optional(string, null) # Full expression for the alert + metric_name = optional(string, "") # Prometheus metric name which queries the data for the alert + metric_function = optional(string, "") # Prometheus function used with metric for queries, like rate, sum etc. + metric_interval = optional(string, "") # The time interval with using functions like rate + settings_mode = optional(string, "replaceNN") # The mode used in B block, possible values are Strict, replaceNN, dropNN + settings_replaceWith = optional(number, 0) # The value by which NaN results of the query will be replaced + filters = optional(any, {}) # Filters object to identify each service for alerting + function = optional(string, "mean") # One of Reduce functions which will be used in B block for alerting + equation = string # The equation in the math expression which compares B blocks value with a number and generates an alert if needed. Possible values: gt, lt, gte, lte, e + threshold = number # The value against which B blocks are compared in the math expression })) default = [] description = "This varibale describes alert folders, groups and rules." diff --git a/modules/notifications/README.md b/modules/notifications/README.md index b8d6ae6..988921f 100644 --- a/modules/notifications/README.md +++ b/modules/notifications/README.md @@ -32,7 +32,7 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [notifications](#input\_notifications) | Represents the configuration options for Grafana notification policies. |
object({
contact_point = optional(string, "Slack") # The default contact point to route all unmatched notifications to.
group_by = optional(list(string), ["grafana_folder", "alertname"]) # A list of alert labels to group alerts into notifications by.
group_interval = optional(string, "5m") # Minimum time interval between two notifications for the same group.
repeat_interval = optional(string, "4h") # Minimum time interval for re-sending a notification if an alert is still firing.

policy = optional(object({
contact_point = optional(string, null) # The contact point to route notifications that match this rule to.
continue = optional(bool, false) # Whether to continue matching subsequent rules if an alert matches the current rule. Otherwise, the rule will be 'consumed' by the first policy to match it.
group_by = optional(list(string), [])
mute_timings = optional(list(string), []) # A list of mute timing names to apply to alerts that match this policy.

matcher = optional(object({
label = optional(string, "priority") # The name of the label to match against.
match = optional(string, "=") # The operator to apply when matching values of the given label. Allowed operators are = for equality, != for negated equality, =~ for regex equality, and !~ for negated regex equality.
value = optional(string, "P1") # The label value to match against.
}))
}))
})
| `{}` | no | +| [notifications](#input\_notifications) | Represents the configuration options for Grafana notification policies. |
object({
contact_point = optional(string, "Slack") # The default contact point to route all unmatched notifications to.
group_by = optional(list(string), ["..."]) # A list of alert labels to group alerts into notifications by.
group_interval = optional(string, "5m") # Minimum time interval between two notifications for the same group.
repeat_interval = optional(string, "4h") # Minimum time interval for re-sending a notification if an alert is still firing.

policies = optional(list(object({
contact_point = optional(string, null) # The contact point to route notifications that match this rule to.
continue = optional(bool, false) # Whether to continue matching subsequent rules if an alert matches the current rule. Otherwise, the rule will be 'consumed' by the first policy to match it.
group_by = optional(list(string), ["..."])
mute_timings = optional(list(string), []) # A list of mute timing names to apply to alerts that match this policy.

matchers = optional(list(object({
label = optional(string, "priority") # The name of the label to match against.
match = optional(string, "=") # The operator to apply when matching values of the given label. Allowed operators are = for equality, != for negated equality, =~ for regex equality, and !~ for negated regex equality.
value = optional(string, "P1") # The label value to match against.
})), [])
})), [])
})
| `{}` | no | ## Outputs diff --git a/modules/notifications/main.tf b/modules/notifications/main.tf index ef2410b..10db533 100644 --- a/modules/notifications/main.tf +++ b/modules/notifications/main.tf @@ -1,27 +1,25 @@ resource "grafana_notification_policy" "policy" { - count = var.notifications.policy != null ? 1 : 0 - contact_point = var.notifications.contact_point group_by = var.notifications.group_by group_interval = var.notifications.group_interval repeat_interval = var.notifications.repeat_interval dynamic "policy" { - for_each = var.notifications.policy != null ? [1] : [] + for_each = var.notifications.policies content { - contact_point = var.notifications.policy.contact_point - continue = var.notifications.policy.continue - group_by = var.notifications.policy.group_by - mute_timings = var.notifications.policy.mute_timings + contact_point = policy.value.contact_point + continue = policy.value.continue + group_by = policy.value.group_by + mute_timings = policy.value.mute_timings dynamic "matcher" { - for_each = var.notifications.policy.matcher.label != null ? [1] : [0] + for_each = policy.value.matchers content { - label = var.notifications.policy.matcher.label - match = var.notifications.policy.matcher.match - value = var.notifications.policy.matcher.value + label = matcher.value.label + match = matcher.value.match + value = matcher.value.value } } } diff --git a/modules/notifications/variables.tf b/modules/notifications/variables.tf index c74d1eb..ea1f1aa 100644 --- a/modules/notifications/variables.tf +++ b/modules/notifications/variables.tf @@ -1,22 +1,22 @@ variable "notifications" { type = object({ - contact_point = optional(string, "Slack") # The default contact point to route all unmatched notifications to. - group_by = optional(list(string), ["grafana_folder", "alertname"]) # A list of alert labels to group alerts into notifications by. - group_interval = optional(string, "5m") # Minimum time interval between two notifications for the same group. - repeat_interval = optional(string, "4h") # Minimum time interval for re-sending a notification if an alert is still firing. + contact_point = optional(string, "Slack") # The default contact point to route all unmatched notifications to. + group_by = optional(list(string), ["..."]) # A list of alert labels to group alerts into notifications by. + group_interval = optional(string, "5m") # Minimum time interval between two notifications for the same group. + repeat_interval = optional(string, "4h") # Minimum time interval for re-sending a notification if an alert is still firing. - policy = optional(object({ + policies = optional(list(object({ contact_point = optional(string, null) # The contact point to route notifications that match this rule to. continue = optional(bool, false) # Whether to continue matching subsequent rules if an alert matches the current rule. Otherwise, the rule will be 'consumed' by the first policy to match it. - group_by = optional(list(string), []) + group_by = optional(list(string), ["..."]) mute_timings = optional(list(string), []) # A list of mute timing names to apply to alerts that match this policy. - matcher = optional(object({ + matchers = optional(list(object({ label = optional(string, "priority") # The name of the label to match against. match = optional(string, "=") # The operator to apply when matching values of the given label. Allowed operators are = for equality, != for negated equality, =~ for regex equality, and !~ for negated regex equality. value = optional(string, "P1") # The label value to match against. - })) - })) + })), []) + })), []) }) description = "Represents the configuration options for Grafana notification policies." default = {} diff --git a/tests/base/1-example.tf b/tests/base/1-example.tf index 94ecd01..dca24c9 100644 --- a/tests/base/1-example.tf +++ b/tests/base/1-example.tf @@ -32,4 +32,38 @@ module "this" { } ] } + + alert_rules = [ + { + "datasource" : "prometheus", + "equation" : "gt", + "expr" : "avg(increase(nginx_ingress_controller_request_duration_seconds_sum[3m])) / 10", + "filters" : null, + "folder_name" : "Nginx Alerts", + "function" : "mean", + "name" : "Latency", + "labels" : { + "priorityHigh" : "true", + } + "summary" : "Latency is higher than 3s", + "threshold" : 3 + }, + ] + + notifications = { + "group_interval" : "1m", + "repeat_interval" : "1m", + "contact_point" : "Slack", + "policies" : [ + { + "contact_point" : "OpsGenie", + "continue" : "true", + "matchers" : [{ + "label" : "priorityHigh", + "match" : "=", + "value" : "true" + }] + }, + ] + } } diff --git a/variables.tf b/variables.tf index 02adbbe..13e2730 100644 --- a/variables.tf +++ b/variables.tf @@ -44,11 +44,11 @@ variable "alert_interval_seconds" { variable "alert_rules" { type = list(object({ - name = string # The name of the alert rule - no_data_state = optional(string, "NoData") # Describes what state to enter when the rule's query returns No Data - exec_err_state = optional(string, "Error") # Describes what state to enter when the rule's query is invalid and the rule cannot be executed - summary = optional(string, "") # Rule annotation as a summary - priority = optional(string, "P2") # Rule priority level: P2 is for non-critical alerts, P1 will be set for critical alerts + name = string # The name of the alert rule + no_data_state = optional(string, "NoData") # Describes what state to enter when the rule's query returns No Data + exec_err_state = optional(string, "Error") # Describes what state to enter when the rule's query is invalid and the rule cannot be executed + summary = optional(string, "") # Rule annotation as a summary + labels = optional(map(any), { "priorityLow" : "true" }) folder_name = optional(string, "Main Alerts") # Grafana folder name in which the rule will be created datasource = string # Name of the datasource used for the alert expr = optional(string, null) # Full expression for the alert @@ -99,23 +99,23 @@ variable "opsgenie_endpoints" { variable "notifications" { type = object({ - contact_point = optional(string, "Slack") # The default contact point to route all unmatched notifications to. - group_by = optional(list(string), ["grafana_folder", "alertname"]) # A list of alert labels to group alerts into notifications by. - group_interval = optional(string, "5m") # Minimum time interval between two notifications for the same group. - repeat_interval = optional(string, "4h") # Minimum time interval for re-sending a notification if an alert is still firing. + contact_point = optional(string, "Slack") # The default contact point to route all unmatched notifications to. + group_by = optional(list(string), ["..."]) # A list of alert labels to group alerts into notifications by. + group_interval = optional(string, "5m") # Minimum time interval between two notifications for the same group. + repeat_interval = optional(string, "4h") # Minimum time interval for re-sending a notification if an alert is still firing. - policy = optional(object({ + policies = optional(list(object({ contact_point = optional(string, null) # The contact point to route notifications that match this rule to. continue = optional(bool, false) # Whether to continue matching subsequent rules if an alert matches the current rule. Otherwise, the rule will be 'consumed' by the first policy to match it. - group_by = optional(list(string), []) + group_by = optional(list(string), ["..."]) mute_timings = optional(list(string), []) # A list of mute timing names to apply to alerts that match this policy. - matcher = optional(object({ + matchers = optional(list(object({ label = optional(string, "priority") # The name of the label to match against. match = optional(string, "=") # The operator to apply when matching values of the given label. Allowed operators are = for equality, != for negated equality, =~ for regex equality, and !~ for negated regex equality. value = optional(string, "P1") # The label value to match against. - })) - })) + })), []) + })), []) }) description = "Represents the configuration options for Grafana notification policies." default = {}