Terraform 0.12:无需枚举属性批量增改Map中的对象
Terraform 动态映射对象属性改造方案
问题背景
现有如下结构的Map变量:
stuff = { object-1 = { id = "1" main_value = "blue" additional_in_values = ["red"] additional_out_values = ["green"] more_values = "foo" }, object-2 = { id = "2" main_value = "green" additional_in_values = ["blue"] additional_out_values = ["red"] more_values = "fee" }, object-3 = { id = "3" main_value = "red" additional_in_values = ["green"] additional_out_values = ["blue"] more_values = "fie" } }
需要实现:
- 遍历Map中的每个对象,无需硬编码所有原有属性
- 新增
inbound_all(由main_value与additional_in_values拼接)、outbound_all(由main_value与additional_out_values拼接)属性 - 保留对象所有原有属性
- 支持后续灵活新增、删除或修改属性的场景
现有方案的问题:
local.unmaintainable:硬枚举所有属性,对象属性动态变化时需同步修改,可维护性极差local.transformed-stuff:仅生成新增属性,完全丢失原有对象数据
现有代码
variable "stuff" { type = map(object({ id = string main_value = string additional_in_values = list(string) additional_out_values = list(string) more_values = string })) } locals { unmaintainable = { for stuff_key, stuff_details in var.stuff : stuff_key => { id = stuff_details.id main_value = stuff_details.main_value additional_out_values = stuff_details.additional_out_values additional_in_values = stuff_details.additional_in_values more_values = stuff_details.more_values inbound_all = concat([stuff_details.main_value], stuff_details.additional_in_values) outbound_all = concat([stuff_details.main_value], stuff_details.additional_out_values) } } transformed-stuff = { for stuff_key, stuff_details in var.stuff : stuff_key => { inbound_all = concat([stuff_details.main_value], stuff_details.additional_in_values) outbound_all = concat([stuff_details.main_value], stuff_details.additional_out_values) } } } output "stuff" { value = var.stuff } output "unmaintainable" { value = local.unmaintainable } output "transformed-stuff" { value = local.transformed-stuff }
当前输出
Outputs: stuff = { "object-1" = { "additional_in_values" = [ "red", ] "additional_out_values" = [ "green", ] "id" = "1" "main_value" = "blue" "more_values" = "foo" } "object-2" = { "additional_in_values" = [ "blue", ] "additional_out_values" = [ "red", ] "id" = "2" "main_value" = "green" "more_values" = "foo" } "object-3" = { "additional_in_values" = [ "green", ] "additional_out_values" = [ "blue", ] "id" = "3" "main_value" = "red" "more_values" = "foo" } } transformed-stuff = { "object-1" = { "inbound_all" = [ "blue", "red", ] "outbound_all" = [ "blue", "green", ] } "object-2" = { "inbound_all" = [ "green", "blue", ] "outbound_all" = [ "green", "red", ] } "object-3" = { "inbound_all" = [ "red", "green", ] "outbound_all" = [ "red", "blue", ] } } unmaintainable = { "object-1" = { "additional_in_values" = [ "red", ] "additional_out_values" = [ "green", ] "id" = "1" "inbound_all" = [ "blue", "red", ] "main_value" = "blue" "more_values" = "foo" "outbound_all" = [ "blue", "green", ] } "object-2" = { "additional_in_values" = [ "blue", ] "additional_out_values" = [ "red", ] "id" = "2" "inbound_all" = [ "green", "blue", ] "main_value" = "green" "more_values" = "foo" "outbound_all" = [ "green", "red", ] } "object-3" = { "additional_in_values" = [ "green", ] "additional_out_values" = [ "blue", ] "id" = "3" "inbound_all" = [ "red", "green", ] "main_value" = "red" "more_values" = "fee" "outbound_all" = [ "red", "blue", ] } }
可维护性解决方案
利用Terraform的merge函数或对象展开语法,实现动态合并原有属性与新增属性,无需硬编码原有字段:
基础实现(新增属性+保留原有)
locals { maintainable_transform = { for k, v in var.stuff : k => merge(v, { inbound_all = concat([v.main_value], v.additional_in_values) outbound_all = concat([v.main_value], v.additional_out_values) }) } } output "maintainable_transform" { value = local.maintainable_transform }
扩展场景:删除指定属性
如果需要删除某个原有属性(比如more_values),可以通过属性过滤+合并实现:
locals { maintainable_transform_with_remove = { for k, v in var.stuff : k => merge( # 过滤掉不需要的属性 { for attr, val in v : attr => val if attr != "more_values" }, { inbound_all = concat([v.main_value], v.additional_in_values) outbound_all = concat([v.main_value], v.additional_out_values) } ) } } output "maintainable_transform_with_remove" { value = local.maintainable_transform_with_remove }
扩展场景:修改原有属性值
如果需要修改原有属性(比如把main_value转为大写),直接在merge里重定义该属性即可覆盖原有值:
locals { maintainable_transform_with_modify = { for k, v in var.stuff : k => merge(v, { main_value = upper(v.main_value) inbound_all = concat([upper(v.main_value)], v.additional_in_values) outbound_all = concat([upper(v.main_value)], v.additional_out_values) }) } } output "maintainable_transform_with_modify" { value = local.maintainable_transform_with_modify }
输出示例(基础实现)
maintainable_transform = { "object-1" = { "additional_in_values" = [ "red", ] "additional_out_values" = [ "green", ] "id" = "1" "inbound_all" = [ "blue", "red", ] "main_value" = "blue" "more_values" = "foo" "outbound_all" = [ "blue", "green", ] } "object-2" = { "additional_in_values" = [ "blue", ] "additional_out_values" = [ "red", ] "id" = "2" "inbound_all" = [ "green", "blue", ] "main_value" = "green" "more_values" = "fee" "outbound_all" = [ "green", "red", ] } "object-3" = { "additional_in_values" = [ "green", ] "additional_out_values" = [ "blue", ] "id" = "3" "inbound_all" = [ "red", "green", ] "main_value" = "red" "more_values" = "fie" "outbound_all" = [ "red", "blue", ] } }
内容的提问来源于stack exchange,提问作者rpc
相关产品推荐
相关产品推荐

