本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
了解 Terraform 函数、表达式和元参数
对使用声明式配置文件而不是常见编程语言的 IaC 工具的一种批评是,它们使实现自定义编程逻辑变得更加困难。在 Terraform 配置中,这个问题是通过使用函数、表达式和元参数来解决的。
函数
使用代码来配置基础架构的最大优势之一是能够存储常见的工作流程并一次又一次地重复使用它们,通常每次都传递不同的参数。Terraform 函数与 AWS CloudFormation 内部函数类似,尽管它们的语法与编程语言中函数的调用方式更为相似。在本指南的示例中,你可能已经注意到一些 Terraform 函数,例如 substrfile
函数以字符串形式返回文件内容,然后该jsondecode
函数将其转换为对象类型。
resource "example_resource" "example_resource_name" { json_object = jsondecode(file("/path/to/file.json")) }
Expressions
Terraform 还允许使用条件表达式condition
函数类似,不同之处在于它们使用更传统的三元id
属性来创建一个新列表。
resource "example_resource" "example_resource_name" { boolean_value = var.value ? true : false numeric_value = var.value > 0 ? 1 : 0 string_value = var.value == "change_me" ? "New value" : var.value string_value_2 = var.value != "change_me" ? var.value : "New value" } There are two ways to express for loops in a Terraform configuration: resource "example_resource" "example_resource_name" { list_value = [for object in var.ids : object.id] list_value_2 = var.ids[*].id }
元参数
在前面的代码示例中,list_value
和list_value_2
被称为参数。你可能已经熟悉其中一些元参数了。Terraform 还有一些元参数,它们的作用就像参数一样,但有一些额外的功能:
其他元参数允许将函数和表达式功能直接添加到资源中。例如,countcount
元参数的情况下创建两个亚马逊弹性容器服务 (Amazon EKS) 集群。
resource "aws_eks_cluster" "example_0" { name = "example_0" role_arn = aws_iam_role.cluster_role.arn vpc_config { endpoint_private_access = true endpoint_public_access = true subnet_ids = var.subnet_ids[0] } } resource "aws_eks_cluster" "example_1" { name = "example_1" role_arn = aws_iam_role.cluster_role.arn vpc_config { endpoint_private_access = true endpoint_public_access = true subnet_ids = var.subnet_ids[1] } }
以下示例演示如何使用count
元参数创建两个 Amazon EKS 集群。
resource "aws_eks_cluster" "clusters" { count = 2 name = "cluster_${count.index}" role_arn = aws_iam_role.cluster_role.arn vpc_config { endpoint_private_access = true endpoint_public_access = true subnet_ids = var.subnet_ids[count.index] } }
要为每个单位命名,您可以访问资源块中的列表索引,网址为count.index
。但是,如果你想创建多个稍微复杂一点的类似资源怎么办? 这就是 for_for_each
元参数与非常相似count
,不同之处在于你传入的是列表或对象,而不是数字。Terraform 为列表或对象的每个成员创建一个新资源。它与您设置时类似count = length(list)
,不同之处在于您可以访问列表的内容而不是循环索引。
这既适用于项目列表,也适用于单个对象。以下示例将创建两个以 ID id-0
和作id-1
为 ID 的资源。
variable "ids" { default = [ { id = "id-0" }, { id = "id-1" }, ] } resource "example_resource" "example_resource_name" { # If your list fails, you might have to call "toset" on it to convert it to a set for_each = toset(var.ids) id = each.value }
以下示例还将创建两个资源,一个用于贵宾犬 Sparky,另一个用于吉娃娃 Fluffy。
variable "dogs" { default = { poodle = "Sparky" chihuahua = "Fluffy" } } resource "example_resource" "example_resource_name" { for_each = var.dogs breed = each.key name = each.value }
就像你可以使用 count.index 访问 count.index 中的循环索引一样,你可以使用每个对象访问 for_each 循环中每个项目的键和值。由于 for_each 会迭代列表和对象,因此跟踪每个键和值可能会有些混乱。下表显示了使用 for_each 元参数的不同方式以及如何在每次迭代时引用这些值。
示例 | for_each 类型 |
第一次迭代 | 第二次迭代 |
---|---|---|---|
A |
|
|
|
B |
|
|
|
C |
|
|
|
D |
|
|
|
E |
|
|
|
因此var.animals
,如果等于行 E,则可以使用以下代码为每只动物创建一个资源。
resource "example_resource" "example_resource_name" { for_each = var.animals type = each.key breeds = each.value[*].type names = each.value[*].name }
或者,您可以使用以下代码为每只动物创建两个资源。
resource "example_resource" "example_resource_name" { for_each = var.animals.dogs type = "dogs" breeds = each.value.type names = each.value.name } resource "example_resource" "example_resource_name" { for_each = var.animals.cats type = "cats" breeds = each.value.type names = each.value.name }