Terraform - 每次应用时将文件上传到 S3

问题描述 投票:0回答:4

我需要将文件夹上传到S3 Bucket。但是当我第一次申请的时候。它只是上传。但我这里有两个问题:

  1. 上传的版本输出为空。我期望一些 version_id 像 1, 2, 3
  2. 再次运行
    terraform apply
    时,它会显示
    Apply complete! Resources: 0 added, 0 changed, 0 destroyed
    。我希望在运行
    terraform apply
    并创建新版本时始终上传。

我做错了什么?这是我的 Terraform 配置:

resource "aws_s3_bucket" "my_bucket" {
  bucket = "my_bucket_name"

  versioning {
    enabled = true
  }
}

resource "aws_s3_bucket_object" "file_upload" {
  bucket = "my_bucket"
  key    = "my_bucket_key"
  source = "my_files.zip"
}

output "my_bucket_file_version" {
  value = "${aws_s3_bucket_object.file_upload.version_id}"
}
amazon-web-services amazon-s3 terraform terraform-provider-aws
4个回答
44
投票

Terraform 仅在检测到配置和远程对象属性之间存在差异时才对远程对象进行更改。在您到目前为止编写的配置中,配置仅包含文件名。它不包含有关文件内容的任何内容,因此 Terraform 无法对文件更改做出反应。

要进行后续更改,有几个选项:

  • 您可以为每个新版本使用不同的本地文件名。
  • 您可以为每个新版本使用不同的远程对象路径。
  • 您可以使用对象 etag 让 Terraform 识别内容何时发生更改,无论本地文件名或对象路径如何。

在这种情况下,最后一个似乎最接近您想要的。为此,请添加

etag
参数并将其设置为文件的 MD5 哈希值:

resource "aws_s3_bucket_object" "file_upload" {
  bucket = "my_bucket"
  key    = "my_bucket_key"
  source = "${path.module}/my_files.zip"
  etag   = "${filemd5("${path.module}/my_files.zip")}"
}

有了这个额外的参数,Terraform 将检测磁盘上文件的 MD5 哈希何时与 S3 中远程存储的不同,并计划相应地更新对象。


(我不确定

version_id
发生了什么。只要在存储桶上启用版本控制,它就应该可以工作。)


22
投票

现在首选的解决方案是使用

source_hash
属性。请注意,
aws_s3_bucket_object
已替换为
aws_s3_object

locals {
  object_source = "${path.module}/my_files.zip"
}

resource "aws_s3_object" "file_upload" {
  bucket      = "my_bucket"
  key         = "my_bucket_key"
  source      = local.object_source
  source_hash = filemd5(local.object_source)
}

请注意,使用加密时

etag
可能会出现问题。


0
投票

补充@sdgfsdh的答案。

如果您没有单个 zip 文件,而是有多个带有文件夹/子文件夹的文件,并且您想要检测文件中的更改。对于这种情况请使用此代码。

locals {
  folder_path = "folder-name"
}

resource "aws_s3_object" "file_upload" {
  for_each = fileset(local.folder_path, "**/*")

  bucket      = "my_bucket"
  key         = "my_bucket_key"
  source      = "${local.folder_path}/${each.value}"

  source_hash = filemd5("${local.folder_path}/${each.value}")
}

此代码将密切关注

folder-name
文件夹内任何文件的更改。如果任何文件发生更改,它将检测到更改并上传文件。


-7
投票

您不应该使用 Terraform 来执行此操作。 Terraform 应该编排和配置您的基础设施及其配置,而不是文件。也就是说,terraform 不知道您文件的更改。除非您更改它们的名称,否则 terraform 不会更新状态。

此外,最好使用

local-exec
来做到这一点。比如:

resource "aws_s3_bucket" "my-bucket" {
# ...

  provisioner "local-exec" {
     command = "aws s3 cp path_to_my_file ${aws_s3_bucket.my-bucket.id}"
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.