Modules Bicep

Bicep vous permet d’organiser les déploiements en modules. Un module est un fichier Bicep (ou un modèle ARM JSON) qui est 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.

Pour partager des modules avec d’autres personnes de votre organisation, créez une spec de modèle, un registre public 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 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éfinition de la syntaxe

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

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. Toutes ces options sont présentées ci-dessous.

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

Le registre de modules publics est hébergé dans un registre de conteneurs Microsoft (MCR). Le code source et les modules sont stockés dans GitHub. Pour afficher les modules disponibles et leurs versions, consultez l’index des modules du registre Bicep.

The screenshot of public module registry.

Sélectionnez les versions pour afficher les versions disponibles. Vous pouvez également sélectionner Code source pour afficher le code source du module et ouvrir les fichiers Lisez-moi.

Il n’y a que quelques modules publiés actuellement. D’autres modules sont à venir. Si vous souhaitez contribuer au registre, consultez le guide de contribution.

Pour créer un lien vers un module de registre 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 du registre de modules public. Cet alias est prédéfini dans votre configuration.
  • 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 hw 'br/public:samples/hello-world:1.0.2' = {
  name: 'helloWorld'
  params: {
    name: 'John Dole'
  }
}

Notes

br/public est l’alias du registre public. Il peut également être écrit comme

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 hw 'br/public:samples/hello-world:1.0.2' = {
  name: 'helloWorld'
  params: {
    name: 'John Dole'
  }
}

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

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@2021-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@2021-04-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@2021-04-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@2021-04-01' existing = {
  name: 'demogroup1'
}

resource secondRG 'Microsoft.Resources/resourceGroups@2021-04-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@2021-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@2021-04-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