Hello. I am deploying an whole system of AWS server less applications with one Terraform module. Each application has many Lambdas and the logic has been completed to automatically conditionally create ECR, SQS, SNS, Cloudwatch Alarms, and Cloudwatch dashboards. Both on an application level and lambda level. However, the only thing I can’t quite figure out is how to make a conditional loop to group the lambdas in an application based CloudWatch Dashboard. I have individual Dashboards set up for the Lambdas already.
I am defining all the Lambda properties like this
var.tf
variable "applications" {
description = "A collection of applications where each lambda is associated with a list of properties "
type = list(object({
name = string
lambdas = list(object({
name = string
schedule = string
timeout = number
sqs = bool
sqs_delay_seconds = number
sqs_max_message_size = number
sqs_message_retention_seconds = number
sqs_receive_wait_time_seconds = number
}))
}))
default = [{
name = "Application1"
lambdas = [{
name = "Lambda1"
schedule = "cron(30 * ? * * *)"
timeout = 60
sqs = false
sqs_delay_seconds = null
sqs_max_message_size = null
sqs_message_retention_seconds = null
sqs_receive_wait_time_seconds = null
}, {
name = "Lambda2"
schedule = null
timeout = 30
sqs = true
sqs_delay_seconds = 0
sqs_max_message_size = 262144
sqs_message_retention_seconds = 345600
sqs_receive_wait_time_seconds = 0
}]
}, {
name = "Applicaion2"
lambdas = [{
name = "Lambda3"
schedule = "cron(30 * ? * * *)"
timeout = 60
sqs = false
sqs_delay_seconds = null
sqs_max_message_size = null
sqs_message_retention_seconds = null
sqs_receive_wait_time_seconds = null
}, {
name = "Lambda4"
schedule = null
timeout = 30
sqs = true
sqs_delay_seconds = 0
sqs_max_message_size = 262144
sqs_message_retention_seconds = 345600
sqs_receive_wait_time_seconds = 0
}]
}]
}
locals {
lambda_properties = flatten([
for application in var.applications : [
for lambda in application.lambdas : {
application_name = application.name
lambda_name = lambda.name
lambda_schedule = lambda.schedule
lambda_timeout = lambda.timeout
sqs = lambda.sqs
sqs_delay_seconds = lambda.sqs_delay_seconds
sqs_max_message_size = lambda.sqs_max_message_size
sqs_message_retention_seconds = lambda.sqs_message_retention_seconds
sqs_receive_wait_time_seconds = lambda.sqs_receive_wait_time_seconds
}
]
])
environment = terraform.workspace
}
Here’s a snippet of the application level Cloudwatch Dashboard
cloudwatch.tf:
locals {
application_dashboard_body = [
{
type : "metric",
x : 0,
y : 0,
width : 12,
height : 6,
timezone : "-0700",
properties : {
view : "timeSeries",
stacked : false,
copilot : true,
metrics : [for lambda in local.lambda_properties : [
"AWS/Lambda", "Duration", "FunctionName", "${local.environment}-${lambda.application_name}-${lambda.lambda_name}"
]
]
region : "${var.region}",
title : "Duration (average)"
}
}
]
resource "aws_cloudwatch_dashboard" "application" {
for_each = { for application in var.applications : application.name => application }
dashboard_name = "${local.environment}-${each.key}"
dashboard_body = jsonencode({
widgets : concat([{
type : "text",
x : 0,
y : 0,
width : 24,
height : 1,
properties : {
markdown : "# ${local.environment}-${each.key}"
}
}], local.application_dashboard_body)
})
}
However, the problem is that it puts ALL the lambdas, no matter the application in the Dashboard. I need to somehow make a conditional on local.application_dashboard_body
to only include the application the current lambda is in. Here is a hard coded example that would work for Application1:
locals {
application_dashboard_body = [
{
type : "metric",
x : 0,
y : 0,
width : 12,
height : 6,
timezone : "-0700",
properties : {
view : "timeSeries",
stacked : false,
copilot : true,
metrics : [for lambda in local.lambda_properties : [
"AWS/Lambda", "Duration", "FunctionName", "${local.environment}-${lambda.application_name}-${lambda.lambda_name}"
] if lambda.application_name == "Application1"
]
region : "${var.region}",
title : "Duration (average)"
}
}
]
}