

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à.

# Esempio 4: aggiunta del controllo del flusso
<a name="cookbooks-101-basics-ruby"></a>

**Importante**  
Il AWS OpsWorks Stacks servizio ha raggiunto la fine del ciclo di vita il 26 maggio 2024 ed è stato disabilitato sia per i clienti nuovi che per quelli esistenti. Consigliamo vivamente ai clienti di migrare i propri carichi di lavoro verso altre soluzioni il prima possibile. Se hai domande sulla migrazione, contatta il Supporto AWS Team su [AWS re:post](https://repost.aws/) o tramite Premium [AWS Support](https://aws.amazon.com/support).

Alcune ricette sono solo una serie di risorse Chef. In questo caso, all'esecuzione, la ricetta esegue semplicemente ciascuno dei provider di risorse in sequenza. Tuttavia, spesso è utile avere un percorso di esecuzione più sofisticato. Di seguito sono elencati due scenari comuni:
+ Una ricetta deve eseguire la stessa risorsa più volte con diverse impostazioni di attributo.
+ Vanno utilizzate diverse impostazioni di attributo su differenti sistemi operativi.

È possibile affrontare situazioni come queste incorporando strutture di controllo di Ruby nella ricetta. Questa sezione spiega come modificare la ricetta da [Esempio 3: creazione di directory](cookbooks-101-basics-directories.md) per affrontare entrambi gli scenari.

**Topics**
+ [Iterazione](#cookbooks-101-basics-ruby-iteration)
+ [Logica condizionale](#cookbooks-101-basics-ruby-conditional)

## Iterazione
<a name="cookbooks-101-basics-ruby-iteration"></a>

In [Esempio 3: creazione di directory](cookbooks-101-basics-directories.md) è stato illustrato come utilizzare una risorsa `directory` per creare una directory o serie di directory. Tuttavia, supponiamo di voler creare due diverse directory, `/srv/www/config` e `/srv/www/shared`. È possibile implementare una risorsa di directory separata per ciascuna directory, ma questo approccio può rivelarsi complesso se intendi creare molte directory. La seguente ricetta mostra un modo più semplice di gestire l'attività. 

```
[ "/srv/www/config", "/srv/www/shared" ].each do |path|
  directory path do
    mode 0755
    owner 'root'
    group 'root'
    recursive true
    action :create
  end
end
```

Invece di utilizzare una risorsa di directory separata per ciascuna sottodirectory, la ricetta utilizza una raccolta di stringa che contiene i percorsi delle sottodirectory. Il metodo `each` di Ruby esegue la risorsa una volta per ciascun elemento della raccolta, a partire dal primo. Il valore dell'elemento è rappresentato nella risorsa dalla variabile `path`, che in questo caso rappresenta il percorso di directory. È possibile adattare questo esempio con semplicità per creare un qualsiasi numero di sottodirectory.

**Per eseguire la ricetta**

1. Rimanere nella directory `createdir`; tale libro di ricette sarà utilizzato per i prossimi esempi. 

1. Se non è già stato fatto, avviare `kitchen destroy` per iniziare con un'istanza pulita. 

1. Sostituire il codice in `default.rb` con l'esempio ed eseguire `kitchen converge`.

1. Accedere all'istanza; la directory appena creata sarà disponibile in `/srv`.

È possibile utilizzare una tabella hash per specificare due valori per ogni iterazione. La seguente ricetta crea `/srv/www/config` e `/srv/www/shared`, ognuna con una modalità diversa.

```
{ "/srv/www/config" => 0644, "/srv/www/shared" => 0755 }.each do |path, mode_value|
  directory path do
    mode mode_value
    owner 'root'
    group 'root'
    recursive true
    action :create
  end
end
```

**Per eseguire la ricetta**

1. Se non è già stato fatto, avviare `kitchen destroy` per iniziare con un'istanza pulita. 

1. Sostituire il codice in `default.rb` con l'esempio ed eseguire `kitchen converge`.

1. Accedere all'istanza; la directory appena creata sarà disponibile in `/srv` con le modalità specificate.

**Nota**  
OpsWorks Le ricette Stacks utilizzano comunemente questo approccio per estrarre valori dalla [configurazione dello stack e dalla distribuzione JSON](workingcookbook-json.md), che è fondamentalmente una grande tabella hash, e inserirli in una risorsa. Per vedere un esempio, consulta [Ricette di ditribuzione](create-custom-deploy.md).

## Logica condizionale
<a name="cookbooks-101-basics-ruby-conditional"></a>

È anche possibile usare la logica condizionale di Ruby per creare più rami di esecuzione. La seguente ricetta utilizza la logica `if-elsif-else` per estendere l'esempio precedente in modo da creare una sottodirectory denominata `/srv/www/shared`, ma solo su sistemi Ubuntu e Debian. Per tutti gli altri sistemi, registra un messaggio di errore che viene visualizzato nell'output di Test Kitchen.

```
if platform?("debian", "ubuntu")
  directory "/srv/www/shared" do
    mode 0755
    owner 'root'
    group 'root'
    recursive true
    action :create
  end
else
  log "Unsupported system"
end
```

**Per eseguire la ricetta di esempio**

1. Se l'istanza è ancora attiva, eseguire `kitchen destroy` per chiuderla.

1. Sostituire il codice in `default.rb` con il codice di esempio.

1. Modificare `.kitchen.yml` per aggiungere un sistema CentOS 6.4 all'elenco delle piattaforme. La sezione `platforms` del file avrà adesso un aspetto simile al seguente.

   ```
   ...
   platforms:
     - name: ubuntu-12.04
     - name: centos-6.4
   ...
   ```

1. Eseguire `kitchen converge`, che consente di creare un'istanza ed eseguire le ricette per ogni piattaforma in `.kitchen.yml`, in sequenza. 
**Nota**  
Per convergere una sola istanza, aggiungere il nome dell'istanza come parametro. Ad esempio, per convergere la ricetta solo sulla piattaforma Ubuntu, eseguire `kitchen converge default-ubuntu-1204`. In caso di dimenticanza dei nomi della piattaforma, basta eseguire `kitchen list`.

Il messaggio di log dovrebbe essere visualizzato nella parte riservata a CentOS dell'output di Test Kitchen, che sarà simile alla seguente:

```
...
Converging 1 resources
Recipe: createdir::default
* log[Unsupported system] action write[2014-06-23T19:10:30+00:00] INFO: Processing log[Unsupported system] action write (createdir::default line 12)
[2014-06-23T19:10:30+00:00] INFO: Unsupported system
       
[2014-06-23T19:10:30+00:00] INFO: Chef Run complete in 0.004972162 seconds
```

Ora puoi accedere alle istanze e verificare se le directory sono state create o meno. Tuttavia, non puoi eseguire semplicemente `kitchen login` ora. Devi specificare l'istanza aggiungendo il nome della piattaforma, ad esempio `kitchen login default-ubuntu-1204` . 

**Nota**  
Se un comando Test Kitchen richiede un nome di istanza, non è necessario digitare il nome completo. Test Kitchen considera il nome di un'istanza come espressione regolare di Ruby, perciò serve solo un numero di caratteri sufficiente a fornire una corrispondenza univoca. Ad esempio, è possibile convergere la sola istanza Ubuntu eseguendo `kitchen converge ub` o accedendo all'istanza CentOS eseguendo `kitchen login 64`.

A questo punto probabilmente ti starai chiedendo come fa la ricetta a sapere su quale piattaforma è in esecuzione. Per ogni sessione, Chef esegue uno strumento chiamato [Ohai](https://docs.chef.io/ohai.html) che raccoglie i dati di sistema, tra cui la piattaforma, e li rappresenta come una serie di attributi in una struttura chiamata *nodo oggetto*. Il metodo `platform?` di Chef confronta i sistemi tra parentesi con il valore della piattaforma Ohai e restituisce true in caso di corrispondenza.

È possibile fare riferimento al valore di un attributo di nodo direttamente nel codice utilizzando `node['attribute_name']`. Il valore della piattaforma, ad esempio, è rappresentato da `node['platform']`. È possibile, ad esempio, aver scritto l'esempio precedente come segue.

```
if node[:platform] == 'debian' or node[:platform] == 'ubuntu'
  directory "/srv/www/shared" do
    mode 0755
    owner 'root'
    group 'root'
    recursive true
    action :create
  end
else
  log "Unsupported system"
end
```

Un motivo comune per includere una logica condizionale in una ricetta si basa sul fatto che diverse famiglie Linux talvolta utilizzano nomi diversi per pacchetti, directory e così via. Ad esempio, il nome del pacchetto Apache è `httpd` sui sistemi CentOS e `apache2` sui sistemi Ubuntu.

Se serve solo un'altra stringa per diversi sistemi, il metodo [http://docs.chef.io/dsl_recipe.html#value-for-platform](http://docs.chef.io/dsl_recipe.html#value-for-platform) di Chef è una soluzione più semplice rispetto a `if-elsif-else`. La seguente ricetta crea una directory `/srv/www/shared` su sistemi CentOS, una directory `/srv/www/data` su sistemi Ubuntu e `/srv/www/config` su tutti gli altri.

```
data_dir = value_for_platform(
  "centos" => { "default" => "/srv/www/shared" },
  "ubuntu" => { "default" => "/srv/www/data" },
  "default" => "/srv/www/config"
)
directory data_dir do
  mode 0755
  owner 'root'
  group 'root'
  recursive true
  action :create
end
```

`value_for_platform` assegna il percorso appropriato a `data_dir` e la risorsa `directory` utilizza tale valore per creare la directory.

**Per eseguire la ricetta di esempio**

1. Se l'istanza è ancora attiva, eseguire `kitchen destroy` per chiuderla.

1. Sostituire il codice in `default.rb` con il codice di esempio.

1. Esegui `kitchen converge` e quindi accedere a ogni istanza per verificare che siano presenti le directory appropriate.