很抱歉出现基本问题,terraform新手。我在terraform中运行了一些示例,其中许多示例显示了局部变量的声明,即locals,从名称上看,它听起来像是它的范围,是文件的本地变量。我们应该能够将此列表作为变量传递,而不是作为局部变量传递,对吗?例如.此外,示例使用for_each构造或locals.names[count.index],其中count.index=length(locals.names),在terraform中传递和迭代此类列表的最佳方式是什么?
variable "name_list"{
names = ["luke", "Tom", ...]
type = ...
}
文件-main.tf
locals{
names = ["luke", "Tom", "Jerry"]
}
resource "aws..." "example..."{
foreach
}
我已经作为本地人尝试过了,但希望将列表作为变量传递。
如果你熟悉通用编程语言,那么把Terraform模块想象成类似于函数可能会有所帮助,然后模块中的三种不同命名值也有相似之处:
- 一个输入变量就像一个函数参数
- 局部值就像函数中的局部变量
- 输出值类似于返回值
这种类比并不完美,因为在许多语言中,函数只能返回一个值,但Terraform允许模块返回许多单独的命名值。但希望这仍然能让人们更容易想象每一个的范围和目的。
在模块的其他地方,表达式可以引用输入变量和本地值:
var.name_list
指的是您在示例中显示的variable "name_list"
声明local.names
是指您在示例中显示的names
本地值
您提到希望将其与for_each
一起使用,而对于for_each
,重要的是您分配给它的值必须是一个映射或一组字符串。for_each
主要想使用映射,但如果您分配了一个像toset(["a", "b"])
这样的集合,那么为了方便起见,for_each
会将其解释为您编写了tomap({"a" = "a", "b" = "b"})
,因此当您遇到没有任何有用值与每个元素关联的情况时,您可以更简洁地编写它。
由于您在示例中显示了一组唯一名称,因此一组字符串似乎就足够了,因此下面的两个示例显示了如何声明一组字符串并在for_each
中使用它,首先使用本地值,然后使用输入变量。
locals {
names = toset(["Luke", "Tom", "Jerry"])
}
resource "example" "example" {
for_each = local.names
# ...
}
variable "names" {
type = set(string)
}
resource "example" "example" {
for_each = var.names
# ...
}
如果在根Terraform模块中使用第二个示例,则在运行terraform apply
时,需要从模块外部设置names
值。有各种不同的方法可以做到这一点,但为了示例起见,一个简单的方法是创建一个名为example.tfvars
的文件,并在其中写入以下内容:
names = ["Luke", "Tom", "Jerry"]
然后,您可以运行terraform apply -var-file=example.tfvars
来使用该组名称应用此配置。请注意,您不需要(也绝不能)在.tfvars
文件中写入toset(...)
,因为对于输入变量,它是模块本身的责任来决定类型,就像我们在上面的配置中编写type = set(string)
一样。因此,Terraform在将该值传递到模块之前,将自动有效地通过toset
传递该值。
您通常应该只使用根模块输入变量来表示您期望的值。在不编辑模块自己的源代码的情况下,需要在运行之间更改这些值。对于作为模块定义一部分的固定内容,局部值是更好的选择。
在您对变量类型的理解中,似乎有些事情混淆了。有局部变量(用locals
块表示)和输入变量[1](它们以variable
开头,通常在单独的文件中定义)。文档中关于locals
[2]的说明:
局部值有助于避免在配置中多次重复相同的值或表达式,但如果过度使用,它们也会隐藏实际使用的值,使配置难以被未来的维护人员读取。
只有在多个地方使用单个值或结果,并且该值将来可能会更改的情况下,才适度使用本地值。在中心位置轻松更改值的能力是本地值的关键优势。
为了进一步扩展,您的问题中有一些不准确之处。例如,count.index
仅与count
元参数一起使用,而不与for_each
一起使用。后者需要有一套或一张地图。如果要将类型为list的变量(本地变量或输入变量)与for_each
一起使用,可以使用toset
[3]内置函数将其强制转换为集合。
为了继续,如果您已经定义了一个输入变量,您可以使用var.<variable_name>
[4]:来引用它
注意:输入变量是由变量块创建的,但您将它们作为名为var.的对象上的属性引用
为了达到最后一点,关于如何使用for_each
:的局部变量的示例
resource "aws..." "example..."{
for_each = toset(local.names)
}
使用声明的输入变量:
resource "aws..." "example..."{
for_each = toset(var.name_list)
}
如您所见,在第二个示例中,您使用的是对象var
,后跟变量名,即var.name_list
。
[1]https://developer.hashicorp.com/terraform/language/values/variables
[2]https://developer.hashicorp.com/terraform/language/values/locals#when-使用本地值
[3]https://developer.hashicorp.com/terraform/language/functions/toset
[4]https://developer.hashicorp.com/terraform/language/values/variables#using-输入变量值