首页 > 解决方案 > 如何在 terraform 13.5 中将变量传递给 google_storage_bucket_object

问题描述

我有一个谷歌存储桶对象,它被创建(通过 terraform),如下所示:

resource "google_storage_bucket_object" "my_post_startup_script" {
  name   = "my-script.sh"
  source = "${path.module}/my-script.sh"
  bucket = my_bucket
}

但是在那个脚本里面是我想做变量的东西。

所以说 my-script.sh 看起来像:

#!/bin/bash
echo "hello ${name}"

有没有办法让我传递一个变量以便进行插值,以便上传的脚本实际上说“你好约翰”

这可能需要一些中间步骤来创建一个带有变量插值的文件,然后我可以将其作为 google_storage_bucket_object 的源传入 - 但不确定如何完成。

标签: google-cloud-storageterraforminterpolation

解决方案


到目前为止,按照您编写的方式,读取文件的是 Google 提供程序本身,my-script.sh因此到那时,任何进一步的 Terraform 模板处理都为时已晚;模板处理是 Terraform 语言本身的一部分,发生在将配置传递给提供者之前。

但是,google_storage_bucket_object还有一个替代参数content,它允许您将所需的内容直接传递给提供者,而提供者不需要从文件本身中读取它。以最简单的形式,允许您将常量值发送到提供程序而无需先将它们写入磁盘:

resource "google_storage_bucket_object" "my_post_startup_script" {
  name   = "my-script.sh"
  bucket = my_bucket

  content = "Hello world!"
}

但是,该content参数可以采用任何返回字符串的有效 Terraform 语言表达式,一个这样的例子是调用templatefile,这是一个要求 Terraform 本身(核心运行时,而不是提供者)从磁盘读取文件并解释的函数其内容为字符串模板

把这两件事放在一起,你可以这样做:

resource "google_storage_bucket_object" "my_post_startup_script" {
  name   = "my-script.sh"
  bucket = my_bucket

  content = templatefile("${path.module}/my-script.sh", {
    name = var.example_name
  })
}

对于您在此处共享的简单示例,无论是 Terraform 本身还是最终从磁盘读取文件的 Google Cloud Platform 提供程序都没有太大的区别,但是在其他方面可能存在一些重要的实际差异情况:

  • Terraform 字符串始终是 Unicode 字符序列而不是原始字节,因此传递值 usingcontent要求内容是 Unicode 字符串,并且提供程序在保存之前会将其编码为 UTF-8。source另一方面,如果您使用,则提供程序将完全按原样获取文件中的原始字节并上传它们,因此您可以上传其他字符编码的文本或上传根本不是文本的文件。
  • 因为它现在是渲染发送给提供者的模板所产生的字符串,而不仅仅是文件名,所以您将看到内容本身显示在 Terraform 计划输出中content,而source您之前只会看到文件名。在许多情况下,人们认为这是使用的优势content不是劣势,但如果内容特别大(从而使计划输出很长)或包含不适合在控制台输出。
  • Terraform 资源配置的大小存在实际限制,这取决于各种技术细节,例如提供程序协议、SDK 和系统上可用的内存,因此content仅适用于相对较小的对象,例如脚本和其他小的配置文件。

如果您的用例包括处理收集在子目录中的大量模板文件,您可能会发现Terraform 模块hashicorp/dir/template很有用。它包装了函数调用templatefilefileset函数调用,以准备一次全部上传的多个文件,并以您可以方便地google_storage_bucket_object使用for_each.


推荐阅读