Reputation: 18529
I wish to create multiple metric filters with multiple alarms & actions. Here's what I have so far. I keep getting an error when trying to parameterize "alarm_actions" part without repeatedly typing the alarm action ARN manually :
# variables.tf
# 2 Log groups - group1 & group2
variable "log_groups" {
type = list(object({})
default = [
{
name = "group1"
retention_in_days = 10
},
{
name = "group2"
retention_in_days = 7
},
]
}
# Metric filters - 2 for group1 & 1 for group2
variable "metric_filters" {
type = list(object({}))
default = [
# Group1 - Metric filters
{
name = "group1-filter1"
pattern = "abc"
group = "group1"
},
{
name = "group1-filter2"
pattern = "xyz"
group = "group1"
},
# Group2 - Metric filters
{
name = "group2-filter1"
pattern = "abcdef"
group = "group2"
},
]
}
# Alarms - with variable number of actions
variable "alarms" {
type = list(object({}))
default = [
{
name = "group1-filter1-alarm"
period = 120
alarm_actions = ["action1"]
},
{
name = "group1-filter2-alarm"
period = 300
alarm_actions = ["action1", "action2"]
},
{
name = "group2-filter1-alarm"
period = 60
alarm_actions = []
},
]
}
Now creating the resources for log groups & metric filters is straight forward (although I would wish to avoid repeating the log group names in variables, but I can live with that)
resource "aws_cloudwatch_log_group" "log_groups" {
for_each = { for x in var.log_groups : x.name => x }
name = each.value.name
retention_in_days = each.value.retention_in_days
}
resource "aws_cloudwatch_log_metric_filter" "metric_filters" {
for_each = { for x in var.metric_filters : x.name => x }
name = each.value.name
pattern = each.value.pattern
log_group_name = each.value.group
metric_transformation {
name = each.value.name
namespace = "xyz-namespace"
value = "1"
}
}
The problem is with creating alarm_actions without repeating my code. How do I declare the ARN of the SNS notifications once as a variable and then reuse them in variables (I guess terraform doesn't allow variables inside variables). Alternatively, I can use the data
functionality to get the SNS by names but a nested for loop for alarm_actions fails inside the alarm resource block :
data "aws_sns_topic" "action1" {
name = "action1"
}
data "aws_sns_topic" "action2" {
name = "action2"
}
resource "aws_cloudwatch_metric_alarm" "alarms" {
for_each = { for x in var.alarms : x.name => x }
alarm_name = each.value.name
comparison_operator = "GreaterThan"
evaluation_periods = "1"
metric_name = each.value.name
namespace = "xyz-namespace"
period = each.value.period
statistic = "Sum"
threshold = "1"
alarm_actions = [for a in each.value.alarm_actions : "data.aws_sns_topic.${a}.arn"]
}
The error I'm getting is
Error: "alarm_actions.0" does not match EC2 automation ARN ("^arn:[\\w-]+:automate:[\\w-]+:ec2:(reboot|recover|stop|terminate)$"): "data.aws_sns_topic.action1.arn"
i.e. it looks like the expression data.aws_sns_topic.${a}.arn
gets the value of ${a}
and then treats it like a string
Upvotes: 1
Views: 2568
Reputation: 17574
You can concatenate the ARN if you like:
"arn:aws:sns:us-east-2:841836440000:action1"
that should be simple, you just need a few more items
"arn:aws:sns:{region}:{account}:{name}"
Another option could be to do the loop on the data, like this:
variable "alarms" {
type = list(object({
name = string
period = number
alarm_actions = list(string)
}))
default = [
{
name = "group1-filter1-alarm"
period = 120
alarm_actions = ["action1"]
},{
name = "group1-filter2-alarm"
period = 300
alarm_actions = ["action1", "action2"]
},
]
}
data "aws_sns_topic" "actions" {
for_each = toset(flatten([for x in var.alarms : x.alarm_actions]))
name = each.value
}
resource "aws_cloudwatch_metric_alarm" "alarms" {
for_each = { for x in var.alarms : x.name => x }
alarm_name = each.value.name
comparison_operator = "GreaterThanThreshold"
evaluation_periods = "1"
metric_name = each.value.name
namespace = "xyz-namespace"
period = each.value.period
statistic = "Sum"
threshold = "1"
alarm_actions = [for a in each.value.alarm_actions : data.aws_sns_topic.actions[a].arn]
}
output "actions" {
value = data.aws_sns_topic.actions
}
Tested to work with:
Terraform v0.12.24
+ provider.aws v2.54.0
Upvotes: 4