Terraform遍历含Map的列表按需创建资源报错求助
原始配置与代码
JSON配置
{"serviceConfig": {"city_shared": {"schedules": [{"EcsServiceRestartOrder": ["redis","redis2","redisblahblah"],"Description": "daily","CityRestartCronExpression": "cron(0 4 * * ? *)","CityRestartEnabled": true},{"EcsServiceRestartOrder": ["redis-stg"],"Description": "weekly","CityRestartCronExpression" : "cron(0 4 * * 1 *)","CityRestartEnabled": true}],"MonitoringStartUTC": "0500","MonitoringEndUTC": "2000"}}}
原始Terraform代码
resource "aws_cloudwatch_event_rule" "scheduled_restart" { for_each = { for i in var.serviceConfig.city_shared.schedules : i.Description => i if i.CityRestartEnabled == true } name = "${local.awsResourceName}-${each.value.Description}-scheduled_restart" schedule_expression = each.value.CityRestartCronExpression is_enabled = each.value.CityRestartEnabled } resource "aws_iam_role" "cloudwatch_event_scheduled_restart" { for_each = { for i in var.serviceConfig.city_shared.schedules : i.Description => i if var.serviceConfig.city_shared.schedules.CityRestartEnabled == true } name = "${join("", [local.multiRegionCityPrefix, local.awsResourceName])}-cloudwatch_event_scheduled_restart" assume_role_policy = jsonencode({ "Version" : "2012-10-17", "Statement" : [ { "Effect" : "Allow", "Principal" : { "Service" : "events.amazonaws.com" }, "Action" : "sts:AssumeRole" } ] } ) tags = { tag-key = "${join("", [local.multiRegionCityPrefix, local.awsResourceName])}-cloudwatch_event_scheduled_restart" } }
错误原因解析
第一个错误(aws_iam_role部分)
Error: Unsupported attribute
on cloudwatch_events.tf line 3, in resource "aws_iam_role" "cloudwatch_event_scheduled_restart":
3: if var.serviceConfig.city_shared.schedules.CityRestartEnabled == true }
|----------------
| var.serviceConfig.city_shared.schedules is list of object with 2 elementsThis value does not have any attributes.
原因:var.serviceConfig.city_shared.schedules是对象列表,直接访问列表的CityRestartEnabled属性逻辑错误,应该引用遍历的单个对象i.CityRestartEnabled,而非整个列表。
第二个错误(aws_cloudwatch_event_rule部分)
Error: Unsupported attribute
on cloudwatch_events.tf line 52, in resource "aws_cloudwatch_event_rule" "scheduled_restart":
52: for_each = { for i in var.serviceConfig.city_shared.schedules : i.Description => iThis object does not have an attribute named "Description".
原因:var.serviceConfig变量未明确类型定义,Terraform松散类型推断无法识别schedules列表中对象的Description属性。
修复方案
1. 明确变量类型定义
在variables.tf中添加变量类型约束,确保Terraform能识别对象属性:
variable "serviceConfig" { type = object({ city_shared = object({ schedules = list(object({ EcsServiceRestartOrder = list(string) Description = string CityRestartCronExpression = string CityRestartEnabled = bool })) MonitoringStartUTC = string MonitoringEndUTC = string }) }) description = "Service configuration" }
2. 修正aws_iam_role的for_each逻辑
- 如果只需要单个IAM角色给所有规则使用,直接移除
for_each:
resource "aws_iam_role" "cloudwatch_event_scheduled_restart" { name = "${join("", [local.multiRegionCityPrefix, local.awsResourceName])}-cloudwatch_event_scheduled_restart" assume_role_policy = jsonencode({ "Version" : "2012-10-17", "Statement" : [ { "Effect" : "Allow", "Principal" : { "Service" : "events.amazonaws.com" }, "Action" : "sts:AssumeRole" } ] }) tags = { tag-key = "${join("", [local.multiRegionCityPrefix, local.awsResourceName])}-cloudwatch_event_scheduled_restart" } }
- 如果需要每个启用的schedule对应一个角色,修正for_each的条件判断:
resource "aws_iam_role" "cloudwatch_event_scheduled_restart" { for_each = { for i in var.serviceConfig.city_shared.schedules : i.Description => i if i.CityRestartEnabled == true } name = "${join("", [local.multiRegionCityPrefix, local.awsResourceName])}-${each.value.Description}-cloudwatch_event_scheduled_restart" assume_role_policy = jsonencode({ "Version" : "2012-10-17", "Statement" : [ { "Effect" : "Allow", "Principal" : { "Service" : "events.amazonaws.com" }, "Action" : "sts:AssumeRole" } ] }) tags = { tag-key = "${join("", [local.multiRegionCityPrefix, local.awsResourceName])}-${each.value.Description}-cloudwatch_event_scheduled_restart" } }
3. 验证aws_cloudwatch_event_rule逻辑
第一个资源的for_each逻辑本身正确,只要变量类型定义完成,i.Description就能被正常识别。
最终验证
执行terraform plan,确认能正常遍历启用的schedule,创建对应的CloudWatch Event规则及正确的IAM角色。
内容的提问来源于stack exchange,提问作者fraserc182

