Terraform合并多for_each资源值及解决concat参数报错问题
解决Terraform合并多个for_each创建的azuredevops_environment资源并筛选的问题
问题背景
需求:合并多个通过for_each创建的azuredevops_environment资源(实现环境、测试环境、预览环境等),筛选名称包含"US"的环境ID,用于azuredevops_check_business_hours资源的for_each配置。
使用版本:
- Terraform Version: v1.4.2
- provider registry.terraform.io/microsoft/azuredevops v0.4.0
原代码与执行报错
环境资源定义
# Implementation environments resource "azuredevops_environment" "impl_regional_environment" { for_each = toset(var.environment_regions) project_id = data.azuredevops_project.vrx.id name = "${each.key} - IMPL" description = "${each.key} Implementation Environment. \n**Managed by Terraform**" } # Test environments resource "azuredevops_environment" "test_regional_environment" { for_each = toset(var.environment_regions) project_id = data.azuredevops_project.vrx.id name = "${each.key} - TEST" description = "${each.key} Test Environment. \n**Managed by Terraform**" } # Preview environments resource "azuredevops_environment" "prev_regional_environment" { for_each = toset(var.environment_regions) project_id = data.azuredevops_project.vrx.id name = "${each.key} - PREV" description = "${each.key} Preview Environment. \n**Managed by Terraform**" }
尝试合并筛选的代码
resource "azuredevops_check_business_hours" "us_non-production" { project_id = data.azuredevops_project.vrx.id display_name = "Daily Deployment Window \n**Managed by Terraform**" for_each = {for key, val in concat(azuredevops_environment.impl_regional_environment,azuredevops_environment.test_regional_environment,azuredevops_environment.prev_regional_environment,azuredevops_environment.pcpy_regional_environment): key => val if length(regexall("US - ", val.name)) > 0} target_resource_id = each.value.id target_resource_type = "environment" start_time = "18:00" end_time = "23:30" time_zone = "Central Standard Time" monday = true tuesday = true wednesday = true thursday = true friday = true saturday = true sunday = true }
报错信息
│ Error: Invalid function argument │ │ on modules\project_vrx\vrx_environments\main.tf line 144, in resource "azuredevops_check_business_hours" "us_non-production": │ 144: for_each = {for key, val in concat(azuredevops_environment.impl_regional_environment,azuredevops_environment.test_regional_environment,azuredevops_environment.prev_regional_environment,azuredevops_environment.pcpy_regional_environment): │ ├──────────────── │ │ while calling concat(seqs...) │ │ azuredevops_environment.impl_regional_environment is object with 6 attributes │ │ Invalid value for "seqs" parameter: all arguments must be lists or tuples; got object.
错误原因
concat()函数要求所有参数必须是列表或元组类型,但通过for_each创建的资源实例是Map类型(对象),直接传入concat()会触发类型不匹配错误。
解决方案
需要先将每个资源的Map实例转换为列表(提取所有值),再进行合并,最后通过for表达式筛选并构造符合for_each要求的唯一键Map:
修改后的azuredevops_check_business_hours资源代码
resource "azuredevops_check_business_hours" "us_non-production" { project_id = data.azuredevops_project.vrx.id display_name = "Daily Deployment Window \n**Managed by Terraform**" # 先将每个资源的map转为列表,合并后筛选并构造新的唯一键map for_each = { for env in concat( values(azuredevops_environment.impl_regional_environment), values(azuredevops_environment.test_regional_environment), values(azuredevops_environment.prev_regional_environment), values(azuredevops_environment.pcpy_regional_environment) ) : env.id => env if contains(env.name, "US - ") } target_resource_id = each.value.id target_resource_type = "environment" start_time = "18:00" end_time = "23:30" time_zone = "Central Standard Time" monday = true tuesday = true wednesday = true thursday = true friday = true saturday = true sunday = true }
代码说明
values()函数:将每个azuredevops_environment资源的Map实例转换为包含所有环境对象的列表concat()函数:合并所有环境列表为一个大列表- for表达式:遍历合并后的列表,以环境的
id作为Map的键(保证唯一),筛选出名称包含"US - "的环境对象,最终生成的Map符合for_each的要求
内容的提问来源于stack exchange,提问作者Scott E
相关产品推荐
相关产品推荐

