Aggiungere flessibilità usando parametri e variabili

Completato

Il principale vantaggio offerto dai modelli è la possibilità di riusarli. Con il linguaggio Bicep è possibile scrivere modelli che consentono la distribuzione di più ambienti o più copie delle risorse create.

La società di giocattoli per cui si lavora lancia regolarmente nuovi prodotti ed è quindi necessario ricorrere ai modelli Bicep per creare le risorse di Azure essenziali per ogni lancio di prodotto. È importante evitare di usare nomi di risorse fissi. Molti tipi di risorse di Azure richiedono nomi univoci quindi se si incorporano i nomi nel modello non sarà più possibile riutilizzare il modello per il lancio di altri prodotti. Le risorse, inoltre, dovranno essere distribuite in località diverse a seconda delle aree geografiche in cui verranno commercializzati i giocattoli ed è quindi importante che nei modelli non venga incorporata neppure la posizione delle risorse.

In questa unità si acquisiranno informazioni sui parametri e sulle variabili, due funzionalità di Bicep che possono rendere i modelli flessibili e riutilizzabili. Verranno inoltre presentate le espressioni.

Nota

I comandi riportati in questa unità vengono illustrati per spiegare i concetti. Non eseguire ancora i comandi. Presto sarà possibile provare quanto appreso.

Parametri e variabili

Un parametro consente di introdurre un valore da una posizione esterna al file del modello. Ad esempio, se si distribuisce manualmente il modello usando l'interfaccia della riga di comando di Azure o Azure PowerShell, verrà richiesto di specificare un valore per ogni parametro. È anche possibile creare un file di parametri in cui sono elencati tutti i parametri e i valori che si intende usare per la distribuzione. Se il modello viene distribuito invece da un processo automatizzato come una pipeline di distribuzione, i valori dei parametri possono essere forniti dalla pipeline.

Una variabile viene definita e impostata all'interno del modello. Le variabili consentono di archiviare informazioni importanti in un'unica posizione a cui è possibile fare riferimento da qualsiasi punto del modello, senza dover copiare e incollare.

In genere, è opportuno usare i parametri per gli elementi che cambiano ad ogni distribuzione, ad esempio:

  • Nomi di risorse che devono essere univoci.
  • Posizioni in cui distribuire le risorse.
  • Le impostazioni che influiscono sui prezzi delle risorse, ad esempio gli SKU, i piani tariffari e i numeri di istanze.
  • Le credenziali e le informazioni necessarie per accedere ad altri sistemi non definiti nel modello.

Le variabili costituiscono in genere un'ottima soluzione quando si usano gli stessi valori in tutte le distribuzioni, ma si vuole rendere un valore riutilizzabile all'interno del modello o quando si vogliono usare espressioni per la creazione di valori complessi. È possibile ricorrere alle variabili anche per le risorse che non richiedono nomi univoci.

Suggerimento

È importante prestare particolare attenzione quando si assegnano i nomi ai parametri e alle variabili, in modo che i modelli siano facili da leggere e capire. Accertarsi quindi di usare nomi chiari, descrittivi e coerenti.

Aggiungere un parametro

In Bicep è possibile definire un parametro come illustrato di seguito:

param appServiceAppName string

Nell'elenco seguente vengono analizzate le singole parti che compongono la definizione:

  • param indica a Bicep che si sta definendo un parametro.
  • appServiceAppName è il nome del parametro. Se si distribuisce il modello manualmente, potrebbe essere richiesta l'immissione di un valore ed è quindi importante che il nome sia chiaro e comprensibile. Il nome determina anche il modo in cui si fa riferimento al valore del parametro all'interno del modello, proprio come con i nomi simbolici delle risorse.
  • string è il tipo del parametro. È possibile specificare vari tipi di parametri Bicep, tra cui string per il testo, int per i numeri e bool per i booleani true o false. Se si preferisce usare parametri più complessi, è possibile ricorre ai tipi array e object.

Suggerimento

Cercare di non generalizzare eccessivamente i modelli usando troppi parametri. È consigliabile usare il numero minimo di parametri necessari per adeguarsi allo scenario aziendale. Tenere presente che è sempre possibile modificare i modelli in un secondo momento, se i requisiti cambiano.

Specificare valori predefiniti

Facoltativamente, è possibile specificare un valore predefinito per un parametro. Quando si specifica un valore predefinito, il parametro diventa facoltativo. La persona che distribuisce il modello può specificare un valore. Tuttavia, in assenza di tale specifica, Bicep ricorrerà al valore predefinito.

Di seguito viene illustrato come poter aggiungere un valore predefinito:

param appServiceAppName string = 'toy-product-launch-1'

Nota

In questo esempio, al nome dell'app del Servizio app di Azure è stato assegnato un valore predefinito hardcoded. Ma non è stata una buona idea, in quanto le app del Servizio app di Azure richiedono nomi univoci. Questo problema verrà risolto a breve.

Usare i valori dei parametri nel modello

Dopo aver dichiarato un parametro, è possibile fare riferimento ad esso da qualsiasi punto del modello. Verrà ora illustrato come poter usare il nuovo parametro nella definizione della risorsa:

resource appServiceApp 'Microsoft.Web/sites@2022-03-01' = {
  name: appServiceAppName
  location: 'eastus'
  properties: {
    serverFarmId: appServicePlan.id
    httpsOnly: true
  }
}

Il modello ora usa il valore del parametro per impostare il nome della risorsa dell'app, anziché un valore hardcoded.

Suggerimento

L'estensione Bicep per Visual Studio Code mostra indicatori visivi per segnalare quando non si seguono le procedure consigliate. Ad esempio, visualizza un avviso se si definisce un parametro non usato. Il linter Bicep esegue continuamente questi controlli mentre si lavora.

Aggiungere una variabile

È possibile definire una variabile come illustrato di seguito:

var appServicePlanName = 'toy-product-launch-plan'

Le variabili vengono definite in modo analogo ai parametri, ma con alcune differenze:

  • Usare la parola chiave var per indicare a Bicep che si sta dichiarando una variabile.
  • È necessario specificare un valore per una variabile.
  • Per le variabile non è necessario specificare il tipo. Bicep può determinare il tipo in base al valore impostato.

Espressioni

Quando si scrive un modello, spesso si preferisce non impostare valori hardcoded o chiedere che vengano specificati in un parametro. Si preferisce invece che i valori vengano individuati mentre viene eseguito il modello. È probabile, ad esempio, che si preferisca distribuire tutte le risorse di un modello in una singola area di Azure, ovvero l'area in cui è stato creato il gruppo di risorse. Oppure è possibile scegliere che il nome univoco di una risorsa venga creato automaticamente in base a una particolare strategia di denominazione usata dall'azienda.

Nel linguaggio Bicep, le espressioni costituiscono una funzionalità molto utile per gestire tutti i tipi di scenari interessanti. Nelle sezioni seguenti verranno illustrate alcune delle posizioni in cui è possibile usare le espressioni in un modello Bicep.

Località delle risorse

Quando si scrive e si distribuisce un modello, spesso si preferisce che non sia necessario specificare la posizione di ogni singola risorsa. Si potrebbe invece impostare una semplice regola aziendale per indicare che per impostazione predefinita tutte le risorse devono essere distribuite nella stessa posizione in cui è stato creato il gruppo di risorse.

In Bicep è possibile creare un parametro denominato location e quindi usare un'espressione per impostarne il valore:

param location string = resourceGroup().location

Osservare come nel valore predefinito del parametro Usa una funzione denominata resourceGroup(), che consente di accedere alle informazioni sul gruppo di risorse in cui viene distribuito il modello. In questo esempio, il modello usa la proprietà location. È comune usare questo approccio per distribuire le risorse nella stessa area di Azure del gruppo di risorse.

Se un utente distribuisce questo modello, potrebbe scegliere di sostituire il valore predefinito e specificare una località diversa.

Nota

Alcune risorse di Azure possono essere distribuite solo in determinate posizioni. Potrebbero quindi essere necessari parametri distinti per impostare le località di queste risorse.

È ora possibile inserire nel modello il parametro relativo all'area geografica della risorsa, come illustrato di seguito:

resource appServiceApp 'Microsoft.Web/sites@2022-03-01' = {
  name: appServiceAppName
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    httpsOnly: true
  }
}

Nomi delle risorse

La maggior parte delle risorse di Azure richiede nomi univoci. In questo scenario sono presenti due risorse che richiedono nomi univoci: l'account di archiviazione e l'app del Servizio app di Azure. Richiedere che questi valori vengano impostati come parametri può rendere difficile per chiunque usare il modello, poiché significherebbe trovare un nome non ancora usato da nessun altro utente.

Bicep offre un'altra funzione denominata uniqueString(), che risulta particolarmente utile quando si creano nomi di risorse. Quando si usa questa funzione, è necessario specificare un valore di inizializzazione, che deve essere diverso tra le varie distribuzioni ma coerente in tutte le distribuzioni delle stesse risorse.

Se si sceglie un valore di inizializzazione efficace, si potrà ottenere lo stesso nome ogni volta che si distribuisce lo stesso set di risorse, ma un nome diverso quando si distribuisce un set diverso di risorse usando lo stesso modello. Di seguito viene illustrato il modo in cui è possibile usare la funzione uniqueString():

param storageAccountName string = uniqueString(resourceGroup().id)

Il valore predefinito di questo parametro usa di nuovo la funzione resourceGroup(), come quando è stata impostata la località della risorsa. Stavolta, tuttavia, questa funzione viene usata per ottenere l'ID di un gruppo di risorse. L'ID del gruppo di risorse avrà un aspetto simile al seguente:

/subscriptions/3e57e557-826f-460b-8f1c-4ce38fd53b32/resourceGroups/MyResourceGroup

L'ID del gruppo di risorse contiene l'ID della sottoscrizione di Azure (3e57e557-826f-460b-8f1c-4ce38fd53b32) e il nome del gruppo di risorse (MyResourceGroup). L'ID del gruppo di risorse è spesso adatto per essere usato anche come valore di inizializzazione per i nomi di risorse, pocihé:

  • Ogni volta che si distribuiscono le stesse risorse, queste verranno distribuite nello stesso gruppo di risorse. La funzione uniqueString() restituirà ogni volta lo stesso valore.
  • Se si esegue la distribuzione in due gruppi di risorse diversi della stessa sottoscrizione di Azure, il valore resourceGroup().id sarà diverso perché i nomi dei gruppi di risorse saranno diversi. La funzione uniqueString() restituirà valori diversi per ogni set di risorse.
  • Se si esegue la distribuzione in due sottoscrizioni di Azure diverse, anche se si usa lo stesso nome di gruppo di risorse, il valore resourceGroup().id risulterà diverso perché l'ID sottoscrizione di Azure sarà diverso. La funzione uniqueString() restituirà di nuovo valori diversi per ogni set di risorse.

Suggerimento

È spesso una buona idea usare espressioni di modello per creare nomi di risorse. Per molti tipi di risorse di Azure sono previste regole specifiche per i caratteri consentiti e la lunghezza dei nomi. Incorporando la creazione dei nomi di risorse nel modello, chiunque usi il modello non deve ricordarsi di seguire queste regole.

Stringhe combinate

Se si usa solo la funzione uniqueString() per impostare i nomi di risorse, è probabile che si ottengano nomi univoci ma non significativi. Un nome di risorsa efficace, infatti, deve essere anche descrittivo, in modo che l'obiettivo della risorsa sia chiaro. In molti casi, è necessario creare un nome che combini una parola o una stringa significativa con un valore univoco. I nomi delle risorse, in questo modo, risulteranno al tempo stesso significativi e univoci.

Bicep offre una funzionalità denominata interpolazione di stringhe che consente di combinare più stringhe. Di seguito ne viene illustrato il funzionamento.

param storageAccountName string = 'toylaunch${uniqueString(resourceGroup().id)}'

Il valore predefinito per il parametro storageAccountName si compone ora di due parti:

  • toylaunch è una stringa hardcoded che consente a chiunque osservi la risorsa distribuita in Azure di comprendere l'obiettivo specifico dell'account di archiviazione.
  • ${uniqueString(resourceGroup().id)} consente di chiedere a Bicep di valutare l'output della funzione uniqueString(resourceGroup().id) e di concatenarlo nella stringa.

Suggerimento

In alcuni casi, la funzione uniqueString() crea stringhe che iniziano con un numero. Alcune risorse di Azure come gli account di archiviazione, tuttavia, non supportano nomi che iniziano con un numero. Ecco perché è una buona idea usare l'interpolazione di stringhe per creare nomi di risorse, come nell'esempio precedente.

Selezione degli SKU per le risorse

Gli altri membri del team sono rimasti molto soddisfatti del codice Bicep creato fino a questo punto. Insieme è stato quindi deciso che il modello creato verrà usato anche per distribuire le risorse per supportare tutti i lanci di futuri giocattoli.

Uno dei colleghi ha suggerito di creare ambienti non di produzione per ogni lancio di prodotto, in modo da consentire al team di marketing di testare i siti prima che vengano resi disponibili ai clienti. È tuttavia necessario accertarsi di non investire troppo in ambienti non di produzione e sono stati quindi messi a punto alcuni criteri:

  • Negli ambienti di produzione, gli account di archiviazione verranno distribuiti nello SKU Standard_GRS (archiviazione con ridondanza geografica) per una resilienza elevata. I piani di servizio app verranno distribuiti nello SKU P2v3 per prestazioni elevate.
  • Negli ambienti non di produzione, gli account di archiviazione verranno distribuiti nello SKU Standard_LRS (archiviazione con ridondanza locale). I piani di servizio app verranno distribuiti nello SKU F1 gratuito.

Un modo per soddisfare questi requisiti aziendali è quello di specificare gli SKU per mezzo di parametri. Tuttavia, specificare ogni SKU come parametro può risultare difficile da gestire, soprattutto quando si usano modelli di grandi dimensioni. Un'altra possibilità è quella di incorporare le regole aziendali nel modello usando una combinazione di parametri, variabili ed espressioni.

In primo luogo, è possibile specificare un parametro per indicare se la distribuzione è destinata a un ambiente di produzione o non di produzione:

@allowed([
  'nonprod'
  'prod'
])
param environmentType string

Si noti che in questo codice viene usata una nuova sintassi per specificare un elenco di valori consentiti per il parametro environmentType. Bicep non consentirà a nessuno di distribuire il modello se non specifica uno di questi valori.

In secondo luogo, è possibile creare variabili che determinano gli SKU da usare per l'account di archiviazione e il piano di servizio app in base all'ambiente:

var storageAccountSkuName = (environmentType == 'prod') ? 'Standard_GRS' : 'Standard_LRS'
var appServicePlanSkuName = (environmentType == 'prod') ? 'P2V3' : 'F1'

Anche in questo caso è presente una nuova sintassi, che è possibile scomporre come indicato di seguito.

  • (environmentType == 'prod') restituisce un valore booleano (true o false), a seconda del valore consentito utilizzato per il parametro environmentType.
  • ? viene chiamato operatore ternario e restituisce un'istruzione if/then. Il valore dopo l’operatore ? viene usato se l’espressione è true. Se invece l'espressione restituisce false, viene usato il valore dopo i due punti (:).

È possibile tradurre queste regole in:

  • Per la variabile storageAccountSkuName, se il parametro environmentType è impostato su prod, usare lo SKU Standard_GRS. In caso contrario, usare lo SKU Standard_LRS.
  • Per la variabile appServicePlanSkuName, se il parametro environmentType è impostato su prod, usare lo SKU P2V3 e il livello PremiumV3. In caso contrario, usare lo SKU F1.

Suggerimento

Quando si creano espressioni composte da più parti come questa, è preferibile usare le variabili anziché incorporare le espressioni direttamente nelle proprietà della risorsa. In questo modo, infatti, i modelli risultano più facili da leggere e capire poiché le definizioni delle risorse non vengono mescolate con parti di logica.

Quando si usano parametri, variabili ed espressioni nel modello, è possibile riutilizzare il modello e distribuire rapidamente un nuovo set di risorse. Ad esempio, ogni volta che il reparto marketing chiede di distribuire un nuovo sito Web per il prossimo lancio di un giocattolo, si forniscono nuovi valori di parametro per ogni ambiente che si distribuisce e il gioco è fatto!