Modules Bicep

Bicep vous permet d’organiser les déploiements en modules. Un module est un fichier Bicep (ou un modèle Azure Resource Manager JSON) déployé à partir d’un autre fichier Bicep. Les modules permettent d’améliorer la lisibilité de vos fichiers Bicep en encapsulant les détails complexes de votre déploiement. Vous pouvez également facilement réutiliser des modules pour différents déploiements.

Si vous souhaitez partager des modules avec d’autres personnes de votre organisation, créez une spec de modèle ou un registre privé. Les specs de modèle et les modules de registre ne sont accessibles qu’aux utilisateurs disposant des autorisations adéquates.

Conseil

Le choix entre un registre de modules et des specs de modèle est principalement une question de préférence. Vous devez prendre en compte certaines choses quand vous choisissez entre les deux :

  • Le registre de modules n’est pris en charge que par Bicep. Si vous n’utilisez pas encore Bicep, utilisez les specs de modèle.
  • Le contenu du registre du modules Bicep ne peut être déployé qu’à partir d’un autre fichier Bicep. Les specs de modèle peuvent être déployées directement à partir de l’API, d’Azure PowerShell, d’Azure CLI et du portail Azure. Vous pouvez même utiliser UiFormDefinition pour personnaliser l’expérience de déploiement du portail.
  • Bicep a des fonctionnalités limitées pour incorporer d’autres artefacts de projet (notamment des fichiers qui ne sont ni Bicep ni des modèles ARM. Par exemple, des scripts PowerShell, des scripts d’interface CLI et d’autres fichiers binaires) en utilisant les fonctions loadTextContent et loadFileAsBase64. Les specs de modèle ne peuvent pas empaqueter ces artefacts.

Les modules Bicep sont convertis en un seul modèle Azure Resource Manager avec des modèles imbriqués. Pour découvrir plus d’informations sur la façon dont Bicep résout les fichiers config et comment Bicep fusionne le fichier config défini par l’utilisateur avec le fichier config par défaut, consultez Processus de résolution de fichier config et Processus de fusion de fichier config.

Ressources de formation

Si vous préférez découvrir les modules via des instructions d’aide pas à pas, consultez Créer des fichiers Bicep composables en utilisant des modules.

Définir des modules

La syntaxe de base pour définir un module est la suivante :

@<decorator>(<argument>)
module <symbolic-name> '<path-to-file>' = {
  name: '<linked-deployment-name>'
  params: {
    <parameter-names-and-values>
  }
}

Ainsi, un exemple simple et concret ressemblerait à ce qui suit :

module stgModule '../storageAccount.bicep' = {
  name: 'storageDeploy'
  params: {
    storagePrefix: 'examplestg1'
  }
}

Vous pouvez également utiliser un modèle ARM JSON en tant que module :

module stgModule '../storageAccount.json' = {
  name: 'storageDeploy'
  params: {
    storagePrefix: 'examplestg1'
  }
}

Utilisez le nom symbolique pour référencer le module dans une autre partie du fichier Bicep. Par exemple, vous pouvez utiliser le nom symbolique pour obtenir la sortie d’un module. Le nom symbolique peut contenir les lettres a à z et A à Z, les chiffres 0 à 9 et le trait de soulignement (_). Le nom ne peut pas commencer par un chiffre. Un module ne peut pas avoir le même nom qu’un paramètre, un module ou une ressource.

Le chemin d’accès peut être un fichier local ou un fichier dans un registre. Le fichier local peut être un fichier Bicep ou un modèle ARM JSON. Pour plus d’informations, consultez Chemin d’accès au module.

La propriété nom est obligatoire. Elle devient le nom de la ressource de déploiement imbriquée dans le modèle généré.

Si un module portant un nom statique est déployé simultanément dans la même étendue, il est possible qu’un déploiement interfère avec la sortie de l’autre déploiement. Par exemple, si deux fichiers Bicep utilisent le même module avec le même nom statique (examplemodule) et ciblent le même groupe de ressources, un déploiement peut afficher la mauvaise sortie. Si l’existence de déploiements simultanés dans la même étendue vous préoccupe, attribuez un nom unique à votre module.

L’exemple suivant concatène le nom du déploiement au nom du module. Si vous fournissez un nom unique pour le déploiement, le nom du module est également unique.

module stgModule 'storageAccount.bicep' = {
  name: '${deployment().name}-storageDeploy'
  scope: resourceGroup('demoRG')
}

Si vous devez spécifier une étendue qui est différente de celle du fichier principal, ajoutez la propriété étendue. Pour plus d’informations, consultez Définir l’étendue du module.

// deploy to different scope
module <symbolic-name> '<path-to-file>' = {
  name: '<linked-deployment-name>'
  scope: <scope-object>
  params: {
    <parameter-names-and-values>
  }
}

Pour déployer un module de manière conditionnelle, ajoutez une expression if. L’utilisation est similaire au déploiement conditionnel d’une ressource.

// conditional deployment
module <symbolic-name> '<path-to-file>' = if (<condition-to-deploy>) {
  name: '<linked-deployment-name>'
  params: {
    <parameter-names-and-values>
  }
}

Pour déployer plus d’une instance d’un module, ajoutez l’expression for. Vous pouvez utiliser l’élément décoratif batchSize pour spécifier si les instances sont déployées en série ou en parallèle. Pour plus d’informations, consultez Boucles itératives dans Bicep.

// iterative deployment
@batchSize(int) // optional decorator for serial deployment
module <symbolic-name> '<path-to-file>' = [for <item> in <collection>: {
  name: '<linked-deployment-name>'
  params: {
    <parameter-names-and-values>
  }
}]

À l’instar des ressources, les modules sont déployés en parallèle, sauf s’ils dépendent d’autres modules ou ressources. En général, vous n’avez pas besoin de définir des dépendances car elles sont déterminées de manière implicite. Si vous devez définir une dépendance explicite, vous pouvez ajouter dependsOn à la définition du module. Pour en savoir plus sur les dépendances, consultez Dépendances des ressources.

module <symbolic-name> '<path-to-file>' = {
  name: '<linked-deployment-name>'
  params: {
    <parameter-names-and-values>
  }
  dependsOn: [
    <symbolic-names-to-deploy-before-this-item>
  ]
}

Chemin d’accès au module

Le fichier du module peut être soit un fichier local, soit un fichier externe. Le fichier externe peut se trouver dans une spec de modèle ou dans un registre de module Bicep.

Fichier local

Si le module est un fichier local, fournissez un chemin d’accès relatif à ce fichier. Tous les chemins d’accès en code Bicep doivent être spécifiés en utilisant le séparateur de répertoires de la barre oblique (/) pour garantir une compilation cohérente entre les plateformes. La barre oblique inverse (\) de Windows n’est pas prise en charge. Les chemins d’accès peuvent contenir des espaces.

Par exemple, pour déployer un fichier qui se trouve à un niveau supérieur dans le répertoire de votre fichier principal, utilisez :

module stgModule '../storageAccount.bicep' = {
  name: 'storageDeploy'
  params: {
    storagePrefix: 'examplestg1'
  }
}

Fichier dans le registre

Registre de module public

Remarque

Les modules non-AVM (Modules vérifiés de Microsoft Azure) sont mis hors service dans le registre de modules public.

Les Modules vérifiés de Microsoft Azure sont des modules prédéfinis, préalablement testés et vérifiés pour déployer des ressources sur Azure. Créés et appartenant à des employés de Microsoft, ces modules sont conçus pour simplifier et accélérer le processus de déploiement pour les configurations et ressources Azure courantes tout en s’alignant également sur les meilleure pratiques, telles qu’Azure Well-Architected Framework​.

Parcourez l’Index Bicep des Modules vérifiés de Microsoft Azure pour voir la liste des modules disponibles. Sélectionnez les nombres mis en évidence dans la capture d’écran suivante pour être directement dirigé vers cette vue filtrée.

Capture d’écran des Modules vérifiés de Microsoft Azure (AVM).

La liste de modules affiche la dernière version. Sélectionnez le numéro de version pour voir la liste des versions disponibles :

Capture d’écran des versions de Modules vérifiés de Microsoft Azure (AVM).

Pour créer un lien vers un module public, spécifiez le chemin d’accès au module avec la syntaxe suivante :

module <symbolic-name> 'br/public:<file-path>:<tag>' = {}
  • br/public est l’alias des modules publics. Vous pouvez personnaliser cet alias dans le fichier config Bicep.
  • Le chemin d’accès au fichier peut contenir des segments séparés par le caractère /.
  • Une balise est utilisée pour spécifier une version du module.

Par exemple :

module storage 'br/public:avm/res/storage/storage-account:0.9.0' = {
  name: 'myStorage'
  params: {
    name: 'store${resourceGroup().name}'
  }
}

Remarque

br/public est l’alias des modules publics. Il peut également être écrit en tant que :

module <symbolic-name> 'br:mcr.microsoft.com/bicep/<file-path>:<tag>' = {}

Registre de module privé

Si vous avez publié un module dans un registre, vous pouvez établir un lien à ce module. Indiquez le nom du registre de conteneurs Azure et un chemin d’accès au module. Spécifiez le chemin d’accès au module avec la syntaxe suivante :

module <symbolic-name> 'br:<registry-name>.azurecr.io/<file-path>:<tag>' = {
  • br est le nom de schéma d’un registre Bicep.
  • Le chemin d’accès au fichier est appelé repository dans Azure Container Registry. Le chemin d’accès au fichier peut contenir des segments séparés par le caractère /.
  • Une balise est utilisée pour spécifier une version du module.

Par exemple :

module stgModule 'br:exampleregistry.azurecr.io/bicep/modules/storage:v1' = {
  name: 'storageDeploy'
  params: {
    storagePrefix: 'examplestg1'
  }
}

Lorsque vous référencez un module dans un registre, l’extension Bicep de Visual Studio Code appelle automatiquement la fonction bicep restore pour copier le module externe dans le cache local. La restauration du module externe prend quelques instants. Si IntelliSense pour le module ne fonctionne pas immédiatement, attendez la fin de la restauration.

Le chemin d’accès complet d’un module dans un registre peut être long. Au lieu de fournir le chemin d’accès complet chaque fois que vous souhaitez utiliser le module, vous pouvez configurer des alias dans le fichier bicepconfig.json. Les alias permettent de référencer plus facilement le module. Par exemple, grâce à un alias, vous pouvez raccourcir le chemin d’accès à :

module stgModule 'br/ContosoModules:storage:v1' = {
  name: 'storageDeploy'
  params: {
    storagePrefix: 'examplestg1'
  }
}

Un alias pour le registre de modules public a été prédéfini :

module storage 'br/public:avm/res/storage/storage-account:0.9.0' = {
  name: 'myStorage'
  params: {
    name: 'store${resourceGroup().name}'
  }
}

Vous pouvez remplacer l’alias public dans le fichier bicepconfig.json.

Fichier dans une spec de modèle

Après avoir créé une spec de modèle, vous pouvez créer un lien vers cette spec de modèle dans un module. Spécifiez la spec de modèle en respectant le format suivant :

module <symbolic-name> 'ts:<sub-id>/<rg-name>/<template-spec-name>:<version>' = {

Vous pouvez toutefois simplifier votre fichier Bicep en créant un alias pour le groupe de ressources qui contient vos specs de modèle. Quand vous utilisez un alias, la syntaxe devient :

module <symbolic-name> 'ts/<alias>:<template-spec-name>:<version>' = {

Le module suivant déploie une spec de modèle pour créer un compte de stockage. L’abonnement et le groupe de ressources associés à la spec de modèle sont définis dans l’alias nommé ContosoSpecs.

module stgModule 'ts/ContosoSpecs:storageSpec:2.0' = {
  name: 'storageDeploy'
  params: {
    storagePrefix: 'examplestg1'
  }
}

Utiliser des décorateurs

Les décorateurs sont écrits au format @expression et sont placés au-dessus des déclarations de modules. Le tableau suivant présente les décorateurs disponibles pour des modules.

Élément décoratif Argument Description
batchSize Aucune Configurez des instances pour un déploiement séquentiel.
description string Fournissez des descriptions pour le module.

Les éléments décoratifs se trouvent dans l’espace de noms sys. Si vous devez différencier un élément décoratif d'un autre élément portant le même nom, faites précéder l’élément décoratif de sys. Par exemple, si votre fichier Bicep contient un paramètre nommé description, vous devez ajouter l’espace de noms sys lors de l’utilisation de l’élément décoratif description.

BatchSize

Vous pouvez uniquement appliquer @batchSize() à une définition de ressource ou de module qui utilise une expression for.

Par défaut, les modules sont déployés en parallèle. Lorsque vous ajoutez l’élément décoratif @batchSize(int), vous déployez des instances en série.

@batchSize(3)
module storage 'br/public:avm/res/storage/storage-account:0.11.1' = [for storageName in storageAccounts: {
  name: 'myStorage'
  params: {
    name: 'store${resourceGroup().name}'
  }
}]

Pour plus d’informations, consultez Déployer par lots.

Description

Pour ajouter une explication, ajoutez une description aux déclarations de modules. Par exemple :

@description('Create storage accounts referencing an AVM.')
module storage 'br/public:avm/res/storage/storage-account:0.9.0' = {
  name: 'myStorage'
  params: {
    name: 'store${resourceGroup().name}'
  }
}

Du texte au format Markdown peut être utilisé pour le texte de description.

Paramètres

Les paramètres que vous fournissez dans votre définition de module correspondent aux paramètres du fichier Bicep.

L’exemple Bicep suivant comporte trois paramètres : storagePrefix, storageSKU et location. Le paramètre storageSKU a une valeur par défaut, de sorte que vous n’avez pas à fournir une valeur pour ce paramètre lors du déploiement.

@minLength(3)
@maxLength(11)
param storagePrefix string

@allowed([
  'Standard_LRS'
  'Standard_GRS'
  'Standard_RAGRS'
  'Standard_ZRS'
  'Premium_LRS'
  'Premium_ZRS'
  'Standard_GZRS'
  'Standard_RAGZRS'
])
param storageSKU string = 'Standard_LRS'

param location string

var uniqueStorageName = '${storagePrefix}${uniqueString(resourceGroup().id)}'

resource stg 'Microsoft.Storage/storageAccounts@2023-04-01' = {
  name: uniqueStorageName
  location: location
  sku: {
    name: storageSKU
  }
  kind: 'StorageV2'
  properties: {
    supportsHttpsTrafficOnly: true
  }
}

output storageEndpoint object = stg.properties.primaryEndpoints

Pour utiliser l’exemple précédent comme module, fournissez des valeurs pour ces paramètres.

targetScope = 'subscription'

@minLength(3)
@maxLength(11)
param namePrefix string

resource demoRG 'Microsoft.Resources/resourceGroups@2024-03-01' existing = {
  name: 'demogroup1'
}

module stgModule '../create-storage-account/main.bicep' = {
  name: 'storageDeploy'
  scope: demoRG
  params: {
    storagePrefix: namePrefix
    location: demoRG.location
  }
}

output storageEndpoint object = stgModule.outputs.storageEndpoint

Définir l’étendue du module

Lors de la déclaration d’un module, vous pouvez définir une étendue pour le module qui est différente de l’étendue pour le fichier Bicep conteneur. Utilisez la propriété scope pour définir l’étendue du module. Lorsque la propriété d’étendue n’est pas fournie, le module est déployé au niveau de l’étendue cible du parent.

Le fichier Bicep suivant crée un groupe de ressources et un compte de stockage dans ce groupe de ressources. Le fichier est déployé dans un abonnement, mais le module est limité au nouveau groupe de ressources.

// set the target scope for this file
targetScope = 'subscription'

@minLength(3)
@maxLength(11)
param namePrefix string

param location string = deployment().location

var resourceGroupName = '${namePrefix}rg'

resource newRG 'Microsoft.Resources/resourceGroups@2024-03-01' = {
  name: resourceGroupName
  location: location
}

module stgModule '../create-storage-account/main.bicep' = {
  name: 'storageDeploy'
  scope: newRG
  params: {
    storagePrefix: namePrefix
    location: location
  }
}

output storageEndpoint object = stgModule.outputs.storageEndpoint

L’exemple suivant déploie des comptes de stockage sur deux groupes de ressources différents. Ces deux groupes de ressources doivent déjà exister.

targetScope = 'subscription'

resource firstRG 'Microsoft.Resources/resourceGroups@2024-03-01' existing = {
  name: 'demogroup1'
}

resource secondRG 'Microsoft.Resources/resourceGroups@2024-03-01' existing = {
  name: 'demogroup2'
}

module storage1 '../create-storage-account/main.bicep' = {
  name: 'westusdeploy'
  scope: firstRG
  params: {
    storagePrefix: 'stg1'
    location: 'westus'
  }
}

module storage2 '../create-storage-account/main.bicep' = {
  name: 'eastusdeploy'
  scope: secondRG
  params: {
    storagePrefix: 'stg2'
    location: 'eastus'
  }
}

Définissez la propriété étendue sur un objet d’étendue valide. Si votre fichier Bicep déploie un groupe de ressources, un abonnement ou un groupe d’administration, vous pouvez définir l’étendue d’un module sur le nom symbolique de cette ressource. Vous pouvez également utiliser les fonctions d’étendue pour obtenir une étendue valide.

Ces fonctions sont les suivantes :

L’exemple suivant utilise la fonction managementGroup pour définir l’étendue.

param managementGroupName string

module mgDeploy 'main.bicep' = {
  name: 'deployToMG'
  scope: managementGroup(managementGroupName)
}

Output

Vous pouvez obtenir des valeurs d’un module et les utiliser dans le fichier Bicep principal. Pour obtenir une valeur de sortie d’un module, utilisez la propriété outputs sur l’objet de module.

Le premier exemple crée un compte de stockage et renvoie les points de terminaison principaux.

@minLength(3)
@maxLength(11)
param storagePrefix string

@allowed([
  'Standard_LRS'
  'Standard_GRS'
  'Standard_RAGRS'
  'Standard_ZRS'
  'Premium_LRS'
  'Premium_ZRS'
  'Standard_GZRS'
  'Standard_RAGZRS'
])
param storageSKU string = 'Standard_LRS'

param location string

var uniqueStorageName = '${storagePrefix}${uniqueString(resourceGroup().id)}'

resource stg 'Microsoft.Storage/storageAccounts@2023-04-01' = {
  name: uniqueStorageName
  location: location
  sku: {
    name: storageSKU
  }
  kind: 'StorageV2'
  properties: {
    supportsHttpsTrafficOnly: true
  }
}

output storageEndpoint object = stg.properties.primaryEndpoints

Lorsqu’il est utilisé en tant que module, vous pouvez récupérer cette valeur de sortie.

targetScope = 'subscription'

@minLength(3)
@maxLength(11)
param namePrefix string

resource demoRG 'Microsoft.Resources/resourceGroups@2024-03-01' existing = {
  name: 'demogroup1'
}

module stgModule '../create-storage-account/main.bicep' = {
  name: 'storageDeploy'
  scope: demoRG
  params: {
    storagePrefix: namePrefix
    location: demoRG.location
  }
}

output storageEndpoint object = stgModule.outputs.storageEndpoint

Étapes suivantes