【问题标题】:How to create a folder in an amazon S3 bucket using terraform如何使用 terraform 在亚马逊 S3 存储桶中创建文件夹
【发布时间】:2016-09-26 06:57:42
【问题描述】:

我能够使用这个link 在亚马逊 S3 中创建一个存储桶。

我使用以下代码创建了一个存储桶:

resource "aws_s3_bucket" "b" {
    bucket = "my_tf_test_bucket"
    acl    = "private"
}

现在我想在存储桶中创建文件夹,比如Folder1

我找到了用于创建 S3 对象的 link。但这有一个强制参数source。我不确定这个值是什么,因为我的意图是在 S3 存储桶中创建一个文件夹。

【问题讨论】:

    标签: amazon-web-services amazon-s3 directory bucket terraform


    【解决方案1】:

    实际上,有一种规范的方法可以创建它,而不依赖于操作系统,通过在 UI 上检查网络,您可以看到内容标题,如:https://stackoverflow.com/users/1554386/alastair-mccormack 所述,

    如今,S3 确实支持从 UI 中看到的文件夹。

    所以你可以这样实现它:

    resource "aws_s3_bucket_object" "base_folder" {
        bucket  = "${aws_s3_bucket.default.id}"
        acl     = "private"
        key     =  "${var.named_folder}/"
        content_type = "application/x-directory"
        kms_key_id = "key_arn_if_used"
    }
    

    注意尾部的斜杠,否则会创建一个空文件

    以上已与 Windows 操作系统一起使用,成功使用 terraform s3_bucket_object 创建文件夹。

    【讨论】:

    • 感谢您的回答,我发现 content_type = "application/x-directory" 比使用 source = "/dev/null" 的公认答案更好地描述 S3 前缀/目录。
    • 这应该是公认的答案,因为它不依赖于操作系统。
    【解决方案2】:

    v0.12.8 引入了一个新的fileset() 函数,它可以与for_each 结合使用以原生支持:

    新功能:

    lang/funcs:新的文件集函数,用于查找静态本地文件 匹配一个全局模式。 (#22523)

    此函数的示例用法如下(来自here):

    # Given the file structure from the initial issue:
    # my-dir
    #    |- file_1
    #    |- dir_a
    #    |     |- file_a_1
    #    |     |- file_a_2
    #    |- dir_b
    #    |     |- file_b_1
    #    |- dir_c
    # And given the expected behavior of the base_s3_key prefix in the initial issue
    
    resource "aws_s3_bucket_object" "example" {
      for_each = fileset(path.module, "my-dir/**/file_*")
    
      bucket = aws_s3_bucket.example.id
      key    = replace(each.value, "my-dir", "base_s3_key")
      source = each.value
    }
    

    在撰写本文时,v0.12.8 已经发布了一天(于 2019 年 9 月 4 日发布),因此https://www.terraform.io/docs/providers/aws/r/s3_bucket_object.html 上的文档尚未引用它。我不确定这是不是故意的。


    顺便说一句,如果您使用上述方法,请记住在您的项目中更新/创建version.tf,如下所示:

    terraform {
      required_version = ">= 0.12.8"
    }
    

    【讨论】:

    • 值得注意的是,如果您走这条路线,它不会根据您的文件设置内容类型,如果您打算使用它来托管网站,这是一个问题。如果您使用外部数据或空资源块(调用 aws s3 同步),您将获得类似的效果,并且它可以正确解释 mime 类型。
    【解决方案3】:

    旧答案,但如果您使用文件夹指定密钥(尚不存在),terraform 将自动为您创建文件夹

    terraform {
      backend "s3" {
        bucket  = "mysql-staging"
        key     = "rds-mysql-state/terraform.tfstate"
        region  = "us-west-2"
        encrypt = true
      }
    }
    

    【讨论】:

      【解决方案4】:

      对于在 Mac 或 Linux 上运行 terraform,以下将做你想做的事

      resource "aws_s3_bucket_object" "folder1" {
          bucket = "${aws_s3_bucket.b.id}"
          acl    = "private"
          key    = "Folder1/"
          source = "/dev/null"
      }
      

      如果您使用的是 Windows,则可以使用空文件。

      虽然人们会对 s3 没有文件夹感到迂腐,但在许多操作中,使用对象占位符作为键前缀(也称为文件夹)会使生活更轻松。例如 s3 同步。

      【讨论】:

      • 是否可以提供多个密钥?
      • 感谢您提供有效的答案,而不是对文件夹的性质过于迂腐。
      • 在 Windows 上,我之前创建了一个空文件,它可以工作,但在 /dev/null 的后面,用于基于 *nix 的东西我想我会尝试 Windows 等价物,它只是 nul,它也可以工作!因此,在上面将 source = "/dev/null" 替换为 source = "nul" 时,它会很有效。
      • 似乎有一个未记录的约定使用application/x-directory 作为内容类型来将文件指定为目录。因此,我成功地将content_type = "application/x-directory" 添加到我的 TF 文件中。致stackoverflow.com/a/44179929/1554386
      • 我刚刚在这里进行了测试,我能够使用content = "" 而不是source = "/dev/null" 创建文件夹。我在 Linux 上,但我想它也应该适用于 Mac 和 Windows。我会说这可能是一个更好的解决方案,因为它不依赖于操作系统。
      【解决方案5】:

      S3 不支持文件夹。对象可以具有带有斜线的前缀名称,看起来像文件夹,但这只是对象名称的一部分。所以没有办法在 terraform 或其他任何东西中创建文件夹,因为在 S3 中没有文件夹之类的东西。

      http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html http://docs.aws.amazon.com/AWSImportExport/latest/DG/ManipulatingS3KeyNames.html

      如果您想假装,您可以在名为“Folder1/”的存储桶中创建一个零字节对象,但这不是必需的。您可以使用“Folder1/File1”之类的键名创建对象,它会起作用。

      【讨论】:

      • 感谢您的信息。但我的疑问是如何创建一个类似于零字节对象的对象。来源应该是什么?
      • 你知道你自己的用例,但关键是,S3 存储桶是完全扁平的,没有 S3 文件夹之类的东西,如果你想在 S3 中放置一个名为 Folder1/File1 的对象,你不需要先“创建”Folder1。如果出于某种原因您仍然真的想这样做,只需在本地文件系统上创建一个零字节文件并将 terraform 指向它作为源。
      • 是的,S3 不支持真正的文件夹,但问题是如何创建 S3 认为可以被视为文件夹的对象。应该接受的答案如下。
      • AWS 有一个创建文件夹按钮。应该有一个等效的 terraform op 来做同样的事情。如果那是在以斜杠结尾的路径上创建一个零内容文件,则 terraform 应该允许它,但我认为它不允许。
      猜你喜欢
      • 2017-03-03
      • 1970-01-01
      • 2011-03-09
      • 1970-01-01
      • 2013-05-23
      • 2011-06-26
      • 1970-01-01
      • 2017-05-25
      • 2018-01-23
      相关资源
      最近更新 更多