如何在terraform中传递和迭代列表变量



很抱歉出现基本问题,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-输入变量值

相关内容

  • 没有找到相关文章

最新更新