从 terraform 上传 AWS S3 中的多个文件

Posted

技术标签:

【中文标题】从 terraform 上传 AWS S3 中的多个文件【英文标题】:Uploading Multiple files in AWS S3 from terraform 【发布时间】:2019-12-18 17:41:00 【问题描述】:

我想将多个文件从本地设备中的特定文件夹上传到 AWS S3。我遇到了以下错误。

这是我的 terraform 代码。

resource "aws_s3_bucket" "testbucket" 
    bucket = "test-terraform-pawan-1"
    acl = "private"

    tags = 
        Name  = "test-terraform"
        Environment = "test"
    


resource "aws_s3_bucket_object" "uploadfile" 
  bucket = "test-terraform-pawan-1"
  key     = "index.html"
  source = "/home/pawan/Documents/Projects/"


我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

从 Terraform 0.12.8 开始,您可以使用 fileset 函数获取给定路径和模式的文件列表。结合for_each,您应该可以将每个文件作为自己的aws_s3_bucket_object 上传:

resource "aws_s3_bucket_object" "dist" 
  for_each = fileset("/home/pawan/Documents/Projects/", "*")

  bucket = "test-terraform-pawan-1"
  key    = each.value
  source = "/home/pawan/Documents/Projects/$each.value"
  # etag makes the file update when it changes; see https://***.com/questions/56107258/terraform-upload-file-to-s3-on-every-apply
  etag   = filemd5("/home/pawan/Documents/Projects/$each.value")

请参阅 GitHub 上的 terraform-providers/terraform-provider-aws : aws_s3_bucket_object: support for directory uploads #3020。

注意:这不会设置像content_type 这样的元数据,据我所知,Terraform 没有内置方法来推断文件的内容类型。此元数据对于诸如从浏览器正常工作的 HTTP 访问之类的事情很重要。如果这对您很重要,您应该考虑手动指定每个文件,而不是尝试自动从文件夹中获取所有内容。

【讨论】:

您可以通过模块指定content_type:registry.terraform.io/modules/hashicorp/dir/template/latest @Flair,这是一个很好的链接!它有一个特定于 S3 的部分直接回答了这个问题。我想留下我的答案,因为不是每个人都需要content_type。您能否引用 S3 示例代码和链接作为单独的答案,以便更明显? 完成!我什至为.tf.json 提供了一个更小的sn-p。【参考方案2】:

您正在尝试上传目录,而 Terraform 需要源字段中的单个文件。尚不支持将文件夹上传到 S3 存储桶。

但是,您可以按照 here 的建议使用 null_resource 配置器调用 awscli 命令。

resource "null_resource" "remove_and_upload_to_s3" 
  provisioner "local-exec" 
    command = "aws s3 sync $path.module/s3Contents s3://$aws_s3_bucket.site.id"
  

【讨论】:

这不会使用与运行 aws_s3_bucket_object 示例相同的安全凭据。【参考方案3】:

自 2020 年 6 月 9 日起,terraform 具有一种内置方法来推断您在上传到 S3 存储桶时可能需要的文件的内容类型(和一些其他属性)

HCL 格式:

module "template_files" 
  source = "hashicorp/dir/template"

  base_dir = "$path.module/src"
  template_vars = 
    # Pass in any values that you wish to use in your templates.
    vpc_id = "vpc-abc123"
  


resource "aws_s3_bucket_object" "static_files" 
  for_each = module.template_files.files

  bucket       = "example"
  key          = each.key
  content_type = each.value.content_type

  # The template_files module guarantees that only one of these two attributes
  # will be set for each file, depending on whether it is an in-memory template
  # rendering result or a static file on disk.
  source  = each.value.source_path
  content = each.value.content

  # Unless the bucket has encryption enabled, the ETag of each object is an
  # MD5 hash of that object.
  etag = each.value.digests.md5

JSON 格式:


"resource": 
  "aws_s3_bucket_object": 
    "static_files": 
      "for_each": "$module.template_files.files"
      #...
      
#...

来源:https://registry.terraform.io/modules/hashicorp/dir/template/latest

【讨论】:

以上是关于从 terraform 上传 AWS S3 中的多个文件的主要内容,如果未能解决你的问题,请参考以下文章

将多个文件上传到 Terraform 中的多个 S3 存储桶

使用 Terraform 将文件上传到 AWS Secrets Manager

如何将旧 S3 存储桶中的 Terraform 状态移动到新的 S3 存储桶?

通过 Terraform 创建的 AWS Glue 中的无效架构错误

terraform/aws lambda 函数访问在 s3 上被拒绝

将文件从 AWS EMR 集群中的映射器上传到 S3