

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Comprensione delle funzioni, delle espressioni e dei meta-argomenti di Terraform
<a name="functions-expressions"></a>

Una critica agli strumenti IaC che utilizzano file di configurazione dichiarativi anziché linguaggi di programmazione comuni è che rendono più difficile l'implementazione di una logica programmatica personalizzata. Nelle configurazioni Terraform, questo problema viene risolto utilizzando funzioni, espressioni e meta-argomenti.

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

Uno dei grandi vantaggi dell'utilizzo del codice per il provisioning dell'infrastruttura è la possibilità di archiviare flussi di lavoro comuni e riutilizzarli più e più volte, spesso passando argomenti diversi ogni volta. Le funzioni Terraform sono simili alle funzioni AWS CloudFormation [intrinseche, sebbene la loro sintassi sia più simile a come le funzioni](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html) vengono chiamate nei linguaggi programmatici. Potresti aver già notato alcune funzioni Terraform, come [substr](https://developer.hashicorp.com/terraform/language/functions/substr), [concat, length e [base64decode](https://developer.hashicorp.com/terraform/language/functions/base64decode)](https://developer.hashicorp.com/terraform/language/functions/concat)[, negli esempi](https://developer.hashicorp.com/terraform/language/functions/length) di questa guida. Come per CloudFormation le funzioni intrinseche, Terraform ha una serie di funzioni [integrate](https://developer.hashicorp.com/terraform/language/functions) che possono essere utilizzate nelle configurazioni. Ad esempio, se un particolare attributo di risorsa richiede un oggetto JSON molto grande che sarebbe inefficiente incollarlo direttamente nel file, è possibile inserire l'oggetto in un **file.json** e utilizzare le funzioni Terraform per accedervi. Nell'esempio seguente, la `file` funzione restituisce il contenuto del file sotto forma di stringa, quindi lo converte in un tipo di oggetto. `jsondecode`

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

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

Terraform consente anche [espressioni condizionali](https://developer.hashicorp.com/terraform/language/expressions/conditionals), che sono simili alle CloudFormation `condition` funzioni tranne per il fatto che utilizzano la più tradizionale sintassi dell'operatore [ternario](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_operator). Nell'esempio seguente, le due espressioni restituiscono esattamente lo stesso risultato. Il secondo esempio è ciò che Terraform chiama espressione [splat](https://developer.hashicorp.com/terraform/language/expressions/splat). L'asterisco fa sì che Terraform scorra l'elenco e crei un nuovo elenco utilizzando solo la `id` proprietà di ciascun 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
}
```

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

*Nell'esempio di codice precedente, `list_value` e `list_value_2` sono indicati come argomenti.* Alcuni di questi meta-argomenti potrebbero già essere familiari. Terraform ha anche alcuni *meta-argomenti*, che agiscono proprio come argomenti ma con alcune funzionalità extra:
+ [Il [meta-argomento depends\_on](https://developer.hashicorp.com/terraform/language/meta-arguments/depends_on) è molto simile all'attributo. CloudFormation DependsOn](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html)
+ Il meta-argomento del [provider](https://developer.hashicorp.com/terraform/language/meta-arguments#provider) consente di utilizzare più configurazioni di provider contemporaneamente.
+ [https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk/RemovalPolicy.html](https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk/RemovalPolicy.html) CloudFormation

Altri meta-argomenti consentono di aggiungere funzionalità di funzioni ed espressioni direttamente a una risorsa. Ad esempio, il meta-argomento [count](https://developer.hashicorp.com/terraform/language/meta-arguments/count) è un meccanismo utile per creare più risorse simili contemporaneamente. L'esempio seguente dimostra come creare due cluster Amazon Elastic Container Service (Amazon EKS) senza utilizzare il `count` meta-argomento.

```
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'esempio seguente mostra come utilizzare il `count` meta-argomento per creare due cluster 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]
  }
}
```

Per assegnare a ciascuna unità un nome, puoi accedere all'indice dell'elenco all'interno del blocco di risorse all'indirizzo. `count.index` Ma cosa succede se si desidera creare più risorse simili ma un po' più complesse? È qui che entra in gioco il [meta-argomento for\_each](https://developer.hashicorp.com/terraform/language/meta-arguments/for_each). Il `for_each` meta-argomento è molto simile a`count`, tranne per il fatto che si passa una lista o un oggetto anziché un numero. Terraform crea una nuova risorsa per ogni membro dell'elenco o dell'oggetto. È simile a se si imposta`count = length(list)`, tranne per il fatto che è possibile accedere al contenuto dell'elenco anziché all'indice del ciclo.

Funziona sia per un elenco di elementi che per un singolo oggetto. L'esempio seguente creerebbe due risorse con `id-0` e `id-1` come loro 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'esempio seguente creerebbe anche due risorse, una per Sparky, il barboncino, e una per Fluffy, il chihuahua.

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

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

Proprio come puoi accedere all'indice del ciclo in count usando count.index, puoi accedere alla chiave e al valore di ogni elemento in un ciclo for\_each utilizzando l'oggetto each. Poiché for\_each esegue iterazioni sia sugli elenchi che sugli oggetti, tenere traccia di ogni chiave e valore può creare un po' di confusione. La tabella seguente mostra i diversi modi in cui è possibile utilizzare il meta-argomento for\_each e come fare riferimento ai valori a ogni iterazione.


****  

| Esempio | `for_each` tipo | Prima iterazione | Seconda iterazione | 
| --- | --- | --- | --- | 
| 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> | 

 

Quindi, se `var.animals` fosse uguale alla riga E, allora potresti creare una risorsa per animale usando il seguente codice.

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

In alternativa, è possibile creare due risorse per animale utilizzando il codice seguente.

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