Terraform从S3加载JSON文件并注入变量的实现方案问询
Terraform:解析S3存储的模板JSON并注入变量
场景说明
本地模板正常工作
我们有一个包含变量占位符的JSON文件:
// fruits.json { "fruits" : { "apples": 3, "bananas": 4, "pears": "${pears}" } }
本地环境下,使用templatefile函数可以直接注入变量:
# main.tf variable "pears" { type = number default = 2 } locals { fruits = templatefile("fruits.json", { pears = var.pears }) }
S3存储后的问题
将该JSON文件上传到S3后,通过aws_s3_bucket_object数据源获取内容时,无法直接用templatefile解析占位符,得到的pears字段是字面量${pears},直接替换也无效:
data "aws_s3_bucket_object" "fruits" { bucket = "fruits" key = "subdir/fruits.json" } locals { data = jsondecode(data.aws_s3_bucket_object.fruits.body) }
解决方案
方法1:单占位符用replace直接替换
如果只有少量占位符,直接用replace函数替换后再解析JSON:
data "aws_s3_bucket_object" "fruits" { bucket = "fruits" key = "subdir/fruits.json" } variable "pears" { type = number default = 2 } locals { templated_body = replace( data.aws_s3_bucket_object.fruits.body, "${pears}", tostring(var.pears) ) fruits = jsondecode(local.templated_body) }
方法2:多占位符用foldl批量替换
如果有多个变量占位符,用foldl遍历变量映射表批量替换:
data "aws_s3_bucket_object" "fruits" { bucket = "fruits" key = "subdir/fruits.json" } variable "pears" { type = number default = 2 } variable "oranges" { type = number default = 5 } locals { var_mapping = { pears = tostring(var.pears) oranges = tostring(var.oranges) } templated_body = foldl( data.aws_s3_bucket_object.fruits.body, [for key, val in local.var_mapping : { k = key, v = val }], (current_body, item) => replace(current_body, "${${item.k}}", item.v) ) fruits = jsondecode(local.templated_body) }
方法3:临时文件配合templatefile(不推荐)
这种方法依赖本地执行环境,兼容性差,仅作备选:
data "aws_s3_bucket_object" "fruits" { bucket = "fruits" key = "subdir/fruits.json" } variable "pears" { type = number default = 2 } # 生成临时模板文件 resource "null_resource" "temp_template" { triggers = { s3_content = data.aws_s3_bucket_object.fruits.body pears_val = var.pears } provisioner "local-exec" { command = "echo '${data.aws_s3_bucket_object.fruits.body}' > ./temp_fruits.json" } } locals { fruits = templatefile("./temp_fruits.json", { pears = var.pears }) } # 清理临时文件 resource "null_resource" "clean_temp" { depends_on = [null_resource.temp_template] provisioner "local-exec" { command = "rm ./temp_fruits.json" } }
内容的提问来源于stack exchange,提问作者yuvi
相关产品推荐
相关产品推荐

