

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Comprendre les fonctions, expressions et méta-arguments de Terraform
<a name="functions-expressions"></a>

L'une des critiques des outils IaC qui utilisent des fichiers de configuration déclaratifs plutôt que des langages de programmation courants est qu'ils compliquent la mise en œuvre d'une logique de programmation personnalisée. Dans les configurations Terraform, ce problème est résolu à l'aide de fonctions, d'expressions et de méta-arguments.

## Fonctions
<a name="functions"></a>

L'un des grands avantages de l'utilisation du code pour provisionner votre infrastructure est la possibilité de stocker des flux de travail courants et de les réutiliser encore et encore, en utilisant souvent des arguments différents à chaque fois. Les fonctions Terraform sont similaires aux [fonctions AWS CloudFormation intrinsèques](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html), bien que leur syntaxe soit plus proche de la façon dont les fonctions sont appelées dans les langages de programmation. [Vous avez peut-être déjà remarqué certaines fonctions Terraform, telles que [substr](https://developer.hashicorp.com/terraform/language/functions/substr), [concat](https://developer.hashicorp.com/terraform/language/functions/concat), length et [base64decode](https://developer.hashicorp.com/terraform/language/functions/base64decode), dans les exemples de ce guide.](https://developer.hashicorp.com/terraform/language/functions/length) Comme CloudFormation pour les fonctions intrinsèques, Terraform possède une série de [fonctions intégrées](https://developer.hashicorp.com/terraform/language/functions) qui peuvent être utilisées dans vos configurations. Par exemple, si un attribut de ressource particulier prend un objet JSON très volumineux qu'il serait inefficace de coller directement dans le fichier, vous pouvez placer l'objet dans un fichier **.json** et utiliser les fonctions Terraform pour y accéder. Dans l'exemple suivant, la `file` fonction renvoie le contenu du fichier sous forme de chaîne, puis le `jsondecode` convertit en un type d'objet.

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

## Expressions
<a name="expressions"></a>

Terraform autorise également les [expressions conditionnelles](https://developer.hashicorp.com/terraform/language/expressions/conditionals), qui sont similaires aux CloudFormation `condition` fonctions, sauf qu'elles utilisent la syntaxe plus traditionnelle des opérateurs [ternaires.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_operator) Dans l'exemple suivant, les deux expressions renvoient exactement le même résultat. Le deuxième exemple est ce que Terraform appelle une expression [splat](https://developer.hashicorp.com/terraform/language/expressions/splat). L'astérisque permet à Terraform de parcourir la liste en boucle et de créer une nouvelle liste en utilisant uniquement la `id` propriété de chaque élément.

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

## Méta-arguments
<a name="meta-arguments"></a>

Dans l'exemple de code précédent, `list_value` et `list_value_2` sont appelés *arguments*. Vous connaissez peut-être déjà certains de ces méta-arguments. Terraform possède également quelques *méta-arguments*, qui agissent comme des arguments mais avec quelques fonctionnalités supplémentaires :
+ [Le méta-argument [depends\$1on](https://developer.hashicorp.com/terraform/language/meta-arguments/depends_on) est très similaire à l'attribut. CloudFormation DependsOn](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html)
+ Le méta-argument du [fournisseur](https://developer.hashicorp.com/terraform/language/meta-arguments#provider) vous permet d'utiliser plusieurs configurations de fournisseur à la fois.
+ Le méta-argument [du cycle](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle) de vie vous permet de personnaliser les paramètres des ressources, de la même manière que les politiques de [suppression](https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk/RemovalPolicy.html) et de [suppression](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) dans. CloudFormation

D'autres méta-arguments permettent d'ajouter des fonctionnalités de fonction et d'expression directement à une ressource. Par exemple, le méta-argument [count](https://developer.hashicorp.com/terraform/language/meta-arguments/count) est un mécanisme utile pour créer plusieurs ressources similaires en même temps. L'exemple suivant montre comment créer deux clusters Amazon Elastic Container Service (Amazon EKS) sans utiliser le `count` méta-argument.

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

L'exemple suivant montre comment utiliser le `count` méta-argument pour créer deux clusters 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]
  }
}
```

Pour attribuer un nom d'unité à chacune, vous pouvez accéder à l'index de la liste dans le bloc de ressources à l'adresse`count.index`. Mais que faire si vous souhaitez créer plusieurs ressources similaires un peu plus complexes ? C'est là qu'intervient le [méta-argument for\$1each](https://developer.hashicorp.com/terraform/language/meta-arguments/for_each). Le `for_each` méta-argument est très similaire à`count`, sauf que vous transmettez une liste ou un objet au lieu d'un nombre. Terraform crée une nouvelle ressource pour chaque membre de la liste ou de l'objet. C'est similaire à si vous définissez`count = length(list)`, sauf que vous pouvez accéder au contenu de la liste plutôt qu'à l'index de la boucle.

Cela fonctionne à la fois pour une liste d'éléments ou pour un seul objet. L'exemple suivant créerait deux ressources qui ont `id-0` et `id-1` comme leur 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
}
```

L'exemple suivant créerait également deux ressources, l'une pour Sparky, le caniche, et l'autre pour Fluffy, le chihuahua.

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

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

Tout comme vous pouvez accéder à l'index de boucle dans count en utilisant count.index, vous pouvez accéder à la clé et à la valeur de chaque élément d'une boucle for\$1each en utilisant l'objet each. Comme for\$1each itère à la fois sur les listes et sur les objets, le suivi de chaque clé et de chaque valeur peut être un peu confus. Le tableau suivant montre les différentes manières d'utiliser le méta-argument for\$1each et la manière dont vous pouvez référencer les valeurs à chaque itération.


****  

| Exemple | `for_each` type | Première itération | Deuxième itération | 
| --- | --- | --- | --- | 
| 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> | 

 

Donc, si `var.animals` c'est égal à la ligne E, vous pouvez créer une ressource par animal en utilisant le code suivant.

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

Vous pouvez également créer deux ressources par animal en utilisant le code suivant.

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