如何在Terraform中用单个资源实现多文件上传至多个S3存储桶
解决方案
该需求完全可以在Terraform中实现,核心思路是先将三个按索引对应的配置项配对,再展平所有待上传文件的映射关系作为for_each的输入,无需拆分多个资源块。
实现逻辑
- 按索引配对
source_file_path、bucket_name、data_folder三个列表的对应项,保证source1对应bucket1、path1的映射关系 - 遍历每个配对项,调用
fileset获取该目录下所有待上传文件,最终展平为全局唯一键的映射,供资源块的for_each使用 - 资源块直接读取映射内的参数完成上传配置
完整代码示例
# 原有变量定义,新增校验规则保证三个列表长度一致 variable "source_file_path"{ type = list(string) description = "Path from where objects are to be uploaded" validation { condition = length(var.source_file_path) == length(var.bucket_name) && length(var.source_file_path) == length(var.data_folder) error_message = "source_file_path、bucket_name、data_folder三个列表的长度必须一致。" } } variable "bucket_name"{ type = list(string) description = "Name or ARN of the bucket to put the file in" } variable "data_folder"{ type = list(string) description = "Object path inside the bucket" } # 新增本地值构造展平的文件映射 locals { # 按索引配对三个配置项,统一处理路径末尾的斜杠 upload_groups = [ for i in range(length(var.source_file_path)) : { source_path = trimsuffix(var.source_file_path[i], "/") bucket = var.bucket_name[i] target_path = trimsuffix(var.data_folder[i], "/") } ] # 遍历每个配置组,提取所有待上传文件构造唯一映射 file_map = merge([ for group in local.upload_groups : { # 第二个参数用**实现递归上传子目录,改为*则仅上传当前目录第一层文件 for file in fileset(group.source_path, "**") : "${group.bucket}/${group.target_path}/${file}" = { bucket = group.bucket source = "${group.source_path}/${file}" target_key = "${group.target_path}/${file}" } } ]...) } # 调整后的上传资源块 resource "aws_s3_bucket_object" "upload_object"{ for_each = local.file_map bucket = each.value.bucket key = each.value.target_key source = each.value.source etag = filemd5(each.value.source) # 基于文件内容生成校验值,仅文件变更时触发重传 }
你原有vars.tfvars的配置无需修改,直接使用即可实现需求。
内容的提问来源于stack exchange,提问作者Bien
相关产品推荐
相关产品推荐

