Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
Comprensión de las funciones, expresiones y metaargumentos de Terraform
Una crítica a las herramientas de IaC que utilizan archivos de configuración declarativos en lugar de lenguajes de programación comunes es que dificultan la implementación de una lógica programática personalizada. En las configuraciones de Terraform, este problema se resuelve mediante funciones, expresiones y metaargumentos.
Funciones
Una de las grandes ventajas de usar código para aprovisionar la infraestructura es la capacidad de almacenar flujos de trabajo comunes y reutilizarlos una y otra vez, con frecuencia utilizando argumentos diferentes cada vez. Las funciones de Terraform son similares a las funciones AWS CloudFormation intrínsecas, aunque su sintaxis es más parecida a la forma en que se denominan las funciones en los lenguajes de programación. Es posible que ya hayas visto algunas funciones de Terraform, como substrfile
función devuelve el contenido del archivo en forma de cadena y, a continuación, lo convierte en un tipo de objeto. jsondecode
resource "example_resource" "example_resource_name" { json_object = jsondecode(file("/path/to/file.json")) }
Expressions
Terraform también admite expresiones condicionalescondition
las funciones, excepto que utilizan la sintaxis de operador ternarioid
propiedad de cada elemento.
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 }
Metaargumentos
En el ejemplo de código anterior, list_value
y se list_value_2
denominan argumentos. Es posible que ya estés familiarizado con algunos de estos metaargumentos. Terraform también tiene algunos metaargumentos, que actúan como argumentos pero con alguna funcionalidad adicional:
-
El metaargumento depends_on
es muy similar al atributo. CloudFormation DependsOn -
El metaargumento del proveedor
le permite usar múltiples configuraciones de proveedores a la vez. -
El metaargumento del ciclo
de vida permite personalizar la configuración de los recursos, de forma similar a como se hace en las políticas de eliminación y eliminación. CloudFormation
Otros metaargumentos permiten añadir funciones y expresiones directamente a un recurso. Por ejemplo, el metaargumento countcount
metaargumento.
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] } }
El siguiente ejemplo muestra cómo utilizar el count
metaargumento para crear dos clústeres de 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] } }
Para asignar a cada uno un nombre de unidad, puede acceder al índice de la lista dentro del bloque de recursos en. count.index
Pero, ¿qué pasa si quieres crear varios recursos similares que sean un poco más complejos? Ahí es donde entra en juego el metaargumento for_eachfor_each
metaargumento es muy similar acount
, excepto que se pasa una lista o un objeto en lugar de un número. Terraform crea un nuevo recurso para cada miembro de la lista u objeto. Es similar a si lo configurascount = length(list)
, excepto que puedes acceder al contenido de la lista en lugar del índice del bucle.
Esto funciona tanto para una lista de elementos como para un solo objeto. El siguiente ejemplo crearía dos recursos que tienen id-0
y id-1
como identificadores.
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 }
En el ejemplo siguiente se crearían también dos recursos, uno para Sparky, el caniche, y otro para Fluffy, el chihuahua.
variable "dogs" { default = { poodle = "Sparky" chihuahua = "Fluffy" } } resource "example_resource" "example_resource_name" { for_each = var.dogs breed = each.key name = each.value }
Del mismo modo que puedes acceder al índice de bucles en count mediante count.index, puedes acceder a la clave y al valor de cada elemento de un bucle for_each utilizando cada objeto. Como for_each recorre listas y objetos, puede resultar un poco confuso realizar un seguimiento de cada clave y valor. En la siguiente tabla se muestran las distintas formas en que se puede utilizar el metaargumento for_each y cómo se puede hacer referencia a los valores en cada iteración.
Ejemplo | for_each type |
Primera iteración | Segunda iteración |
---|---|---|---|
A |
|
|
|
B |
|
|
|
C |
|
|
|
D |
|
|
|
E |
|
|
|
Entonces, si var.animals
fuera igual a la fila E, entonces podrías crear un recurso por animal usando el siguiente código.
resource "example_resource" "example_resource_name" { for_each = var.animals type = each.key breeds = each.value[*].type names = each.value[*].name }
Como alternativa, puedes crear dos recursos por animal mediante el siguiente código.
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 }