

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Entendendo as funções, expressões e meta-argumentos do Terraform
<a name="functions-expressions"></a>

Uma crítica às ferramentas de IaC que usam arquivos de configuração declarativos em vez de linguagens de programação comuns é que elas dificultam a implementação da lógica programática personalizada. Nas configurações do Terraform, esse problema é resolvido usando funções, expressões e meta-argumentos.

## Funções
<a name="functions"></a>

Uma das grandes vantagens de usar código para provisionar sua infraestrutura é a capacidade de armazenar fluxos de trabalho comuns e reutilizá-los repetidamente, geralmente transmitindo argumentos diferentes a cada vez. As funções do Terraform são semelhantes às [funções AWS CloudFormation intrínsecas](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html), embora sua sintaxe seja mais semelhante à forma como as funções são chamadas em linguagens programáticas. Talvez você já tenha notado algumas funções do Terraform, como [substr](https://developer.hashicorp.com/terraform/language/functions/substr), [concat](https://developer.hashicorp.com/terraform/language/functions/concat), [length](https://developer.hashicorp.com/terraform/language/functions/length) e [base64decode](https://developer.hashicorp.com/terraform/language/functions/base64decode), nos exemplos deste guia. Assim como CloudFormation as funções intrínsecas, o Terraform tem uma série de [funções integradas](https://developer.hashicorp.com/terraform/language/functions) que estão disponíveis para uso em suas configurações. Por exemplo, se um determinado atributo de recurso usa um objeto JSON muito grande que seria ineficiente para colar diretamente no arquivo, você poderia colocar o objeto em um **arquivo.json** e usar as funções do Terraform para acessá-lo. No exemplo a seguir, a `file` função retorna o conteúdo do arquivo na forma de string e, em seguida, a `jsondecode` função o converte em um tipo de objeto.

```
resource "example_resource" "example_resource_name" {
  json_object = jsondecode(file("/path/to/file.json"))
}
```

## Expressões
<a name="expressions"></a>

O Terraform também permite [expressões condicionais](https://developer.hashicorp.com/terraform/language/expressions/conditionals), que são semelhantes às CloudFormation `condition` funções, exceto pelo fato de usarem a sintaxe mais tradicional do operador [ternário](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_operator). No exemplo a seguir, as duas expressões retornam exatamente o mesmo resultado. O segundo exemplo é o que o Terraform chama de expressão [splat](https://developer.hashicorp.com/terraform/language/expressions/splat). O asterisco faz com que o Terraform percorra a lista e crie uma nova lista usando apenas a `id` propriedade de cada item.

```
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
}
```

## Meta-argumentos
<a name="meta-arguments"></a>

No exemplo de código anterior, `list_value` e `list_value_2` são chamados de *argumentos*. Talvez você já esteja familiarizado com alguns desses meta-argumentos. O Terraform também tem alguns *meta-argumentos*, que funcionam como argumentos, mas com algumas funcionalidades extras:
+ [O meta-argumento [depends\$1on](https://developer.hashicorp.com/terraform/language/meta-arguments/depends_on) é muito semelhante ao atributo. CloudFormation DependsOn](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html)
+ O meta-argumento do [provedor](https://developer.hashicorp.com/terraform/language/meta-arguments#provider) permite que você use várias configurações de provedor ao mesmo tempo.
+ [O meta-argumento [do ciclo de vida](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle) permite que você personalize as configurações de recursos, de forma semelhante às políticas de [remoção e exclusão](https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk/RemovalPolicy.html) em.](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) CloudFormation

Outros meta-argumentos permitem que a funcionalidade de função e expressão seja adicionada diretamente a um recurso. Por exemplo, o meta-argumento [count](https://developer.hashicorp.com/terraform/language/meta-arguments/count) é um mecanismo útil para criar vários recursos semelhantes ao mesmo tempo. O exemplo a seguir demonstra como criar dois clusters do Amazon Elastic Container Service (Amazon EKS) sem usar o `count` meta-argumento.

```
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]
  }
}
```

O exemplo a seguir demonstra como usar o `count` meta-argumento para criar dois clusters do 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 dar um nome de unidade a cada uma, você pode acessar o índice da lista dentro do bloco de recursos em`count.index`. Mas e se você quiser criar vários recursos semelhantes que sejam um pouco mais complexos? É aí que entra o [meta-argumento for\$1each](https://developer.hashicorp.com/terraform/language/meta-arguments/for_each). O `for_each` meta-argumento é muito semelhante a`count`, exceto que você passa uma lista ou um objeto em vez de um número. O Terraform cria um novo recurso para cada membro da lista ou objeto. É semelhante a se você definir`count = length(list)`, exceto que você pode acessar o conteúdo da lista em vez do índice do loop.

Isso funciona tanto para uma lista de itens quanto para um único objeto. O exemplo a seguir criaria dois recursos que têm `id-0` e `id-1` como seus IDs.

```
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
}
```

O exemplo a seguir também criaria dois recursos, um para Sparky, o poodle, e outro para Fluffy, o chihuahua.

```
variable "dogs" {
  default = {
    poodle    = "Sparky"
    chihuahua = "Fluffy"
  }
}

resource "example_resource" "example_resource_name" {
  for_each = var.dogs
  breed    = each.key
  name     = each.value
}
```

Assim como você pode acessar o índice do loop em count usando count.index, você pode acessar a chave e o valor de cada item em um loop for\$1each usando o objeto each. Como for\$1each itera tanto em listas quanto em objetos, o controle de cada chave e valor pode ser um pouco confuso. A tabela a seguir mostra as diferentes maneiras de usar o meta-argumento for\$1each e como você pode referenciar os valores em cada iteração.


****  

| Exemplo | Tipo de `for_each` | Primeira iteração | Segunda iteração | 
| --- | --- | --- | --- | 
| A | <pre>["poodle", "chihuahua"]</pre> | <pre>each.key = "poodle"<br /><br />each.value = null</pre> | <pre>each.key = "chihuahua"<br /><br />each.value = null</pre> | 
| B | <pre>[<br /><br />{<br /><br />type = "poodle",<br /><br />name = "Sparky"<br /><br />},<br /><br />{<br /><br />type = "chihuahua",<br /><br />name = "Fluffy"<br /><br />}<br /><br />]</pre> | <pre>each.key = {<br /><br />type = "poodle",<br /><br />name = "Sparky"<br /><br />}<br /><br />each.value = null</pre> | <pre>each.key = {<br /><br />type = "chihuahua",<br /><br />name = "Fluffy"<br /><br />}<br /><br />each.value = null</pre> | 
| C | <pre>{<br /><br />poodle = "Sparky",<br /><br />chihuahua = "Fluffy"<br /><br />}</pre> | <pre>each.key = "poodle"<br /><br />each.value = "Sparky"</pre> | <pre>each.key = "chihuahua"<br /><br />each.value = "Fluffy"</pre> | 
| D | <pre>{<br /><br />dogs = {<br /><br />poodle = "Sparky",<br /><br />chihuahua = "Fluffy"<br /><br />},<br /><br />cats = {<br /><br />persian = "Felix",<br /><br />burmese = "Morris"<br /><br />}<br /><br />}</pre> | <pre>each.key = "dogs"<br /><br />each.value = {<br /><br />poodle = "Sparky",<br /><br />chihuahua = "Fluffy"<br /><br />}</pre> | <pre>each.key = "cats"<br /><br />each.value = {<br /><br />persian = "Felix",<br /><br />burmese = "Morris"<br /><br />}</pre> | 
| E | <pre>{<br /><br />dogs = [<br /><br />{<br /><br />type = "poodle",<br /><br />name = "Sparky"<br /><br />},<br /><br />{<br /><br />type = "chihuahua",<br /><br />name = "Fluffy"<br /><br />}<br /><br />],<br /><br />cats = [<br /><br />{<br /><br />type = "persian",<br /><br />name = "Felix"<br /><br />},<br /><br />{<br /><br />type = "burmese",<br /><br />name = "Morris"<br /><br />}<br /><br />]<br /><br />}</pre> | <pre>each.key = "dogs"<br /><br />each.value = [<br /><br />{<br /><br />type = "poodle",<br /><br />name = "Sparky"<br /><br />},<br /><br />{<br /><br />type = "chihuahua",<br /><br />name = "Fluffy"<br /><br />}<br /><br />]</pre> | <pre>each.key = "cats"<br /><br />each.value = [<br /><br />{<br /><br />type = "persian",<br /><br />name = "Felix"<br /><br />},<br /><br />{<br /><br />type = "burmese",<br /><br />name = "Morris"<br /><br />}<br /><br />]</pre> | 

 

Portanto, se `var.animals` fosse igual à linha E, você poderia criar um recurso por animal usando o código a seguir.

```
resource "example_resource" "example_resource_name" {
  for_each = var.animals
  type     = each.key
  breeds   = each.value[*].type
  names    = each.value[*].name
}
```

Como alternativa, você pode criar dois recursos por animal usando o código a seguir.

```
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
}
```