Planifier la structure de votre fichier Bicep

Effectué

Bicep vous offre la possibilité de décider de la façon dont vous structurez votre code. Dans cette unité, vous allez découvrir les différentes méthodes de structuration de code Bicep ainsi que l’importance d’un style cohérent et d’un code Bicep clair et compréhensible.

Quel ordre votre code Bicep doit-il suivre ?

Vos modèles Bicep peuvent contenir de nombreux éléments, notamment des paramètres, des variables, des ressources, des modules, des sorties et un targetScope pour l’ensemble du modèle. Bicep ne vous impose pas de suivre un ordre particulier pour vos éléments. Cependant, il est important de tenir compte de l’ordre de vos éléments pour faire en sorte que votre modèle soit clair et compréhensible.

Il existe deux approches principales en matière d’ordonnancement du code :

  • Regrouper les éléments par type d’élément
  • Regrouper les éléments par ressource

Vous et votre équipe devez en adopter une et l’utiliser systématiquement.

Regrouper les éléments par type d’élément

Vous pouvez regrouper tous les éléments du même type. Tous vos paramètres sont placés à un même endroit, généralement en haut du fichier. Les variables suivront, suivies des ressources et des modules, avec les sorties au bas. Par exemple, vous disposez d’un fichier Bicep qui déploie une base de données Azure SQL et un compte de stockage.

Quand vous regroupez vos éléments par type, voici comment ils peuvent se présenter :

Diagram showing elements grouped by element type. Parameters are grouped together, then variables, then resources, then outputs.

Conseil

Si vous suivez cette convention, envisagez de placer le targetScope en haut du fichier.

Cet ordonnancement paraît logique lorsque vous êtes habitué à d’autres langages d’infrastructure en tant que code (par exemple, le langage des modèles Azure Resource Manager). Il peut également faciliter la compréhension de votre modèle, car il indique clairement où chercher des types d’éléments spécifiques. Dans les modèles plus longs, il peut cependant être difficile de naviguer parmi les éléments et de passer de l’un à l’autre.

Il vous reste encore à décider de la façon d’ordonner les éléments au sein de ces catégories. Il est judicieux de regrouper les paramètres apparentés. Par exemple, tous les paramètres se rapportant à un compte de stockage appartiennent à la même catégorie, laquelle regroupement également les paramètres SKU du compte de stockage.

De la même façon, vous pouvez regrouper les ressources apparentées. Cela permet à quiconque utilisant votre modèle de le parcourir rapidement et d’en identifier les parties importantes.

Parfois, vous pouvez être amené à créer un modèle qui déploie une ressource principale avec plusieurs ressources secondaires. Par exemple, vous pouvez créer un modèle pour déployer un site web hébergé dans Azure App Service. La ressource principale est l’application App Service. Les ressources secondaires au sein du même modèle peuvent inclure le plan App Service, un compte de stockage, une instance Application Insights et d’autres éléments. Si vous avez un modèle analogue, il est judicieux de placer la ou les ressources principales en haut de la section des ressources du modèle : ainsi, quand un utilisateur ouvre le modèle, il peut identifier rapidement sa finalité et trouver les ressources importantes.

Regrouper les éléments par ressource

Vous pouvez aussi regrouper vos éléments en fonction du type des ressources que vous déployez. Pour reprendre l’exemple précédent, vous pouvez regrouper l’ensemble des paramètres, des variables, des ressources et des sorties en rapport avec les ressources de base de données Azure SQL. Vous pouvez ensuite ajouter les paramètres, les variables, les ressources et les sorties pour le compte de stockage, comme indiqué ici :

Diagram showing elements grouped by resource. Storage account elements are grouped, followed by Azure SQL database elements.

Le regroupement par ressource peut faciliter la lecture de votre modèle, car tous les éléments dont vous avez besoin pour une ressource spécifique se trouvent au même endroit. Il est cependant plus difficile de vérifier rapidement comment des types d’éléments spécifiques sont déclarés, par exemple quand vous voulez passer en revue tous vos paramètres.

Vous devez aussi réfléchir à la façon de gérer les paramètres et les variables communs à plusieurs ressources, par exemple un paramètre environmentType, lorsque vous utilisez un mappage de configuration. Les paramètres et les variables communs doivent être placés au même endroit, généralement en haut du fichier Bicep.

Conseil

Voyez s’il est plus judicieux de créer des modules pour les groupes de ressources apparentées et d’utiliser un modèle plus simple pour combiner les modules. Les modules Bicep sont abordés plus en détail dans les parcours d’apprentissage de Bicep.

En quoi l’espace blanc peut-il aider à créer une structure ?

Les lignes vides, ou espaces blancs, peuvent vous aider à ajouter une structure visuelle à votre modèle. En utilisant l’espace blanc de manière réfléchie, vous pouvez regrouper logiquement les sections de votre code Bicep, ce qui peut contribuer à clarifier les relations entre les ressources. Pour ce faire, envisagez d’ajouter une ligne vide entre les principales sections, quel que soit le style de regroupement choisi.

Comment définir plusieurs ressources similaires ?

Avec Bicep, vous pouvez utiliser des boucles pour déployer des ressources similaires à partir d’une définition unique. En utilisant le mot clé for pour définir des boucles de ressources, vous pouvez améliorer la clarté de votre code Bicep et limiter la duplication inutile de définitions de ressources. Par la suite, quand vous aurez besoin de modifier la définition de vos ressources, il vous suffira d’effectuer une mise à jour à un seul endroit. Par défaut, au moment déployer vos ressources, Azure Resource Manager déploie toutes les ressources de la boucle à la fois, ce qui optimise l’efficacité de votre déploiement.

Recherchez les endroits où plusieurs ressources identiques sont définies ou dont les propriétés présentent peu de différences. Ensuite, ajoutez une variable pour lister les ressources à créer ainsi que les propriétés qui diffèrent des autres ressources. L’exemple suivant utilise une boucle pour définir un ensemble de conteneurs Azure Cosmos DB, chacun possédant son propre nom et sa propre clé de partition :

var cosmosDBContainerDefinitions = [
  {
    name: 'customers'
    partitionKey: '/customerId'
  }
  {
    name: 'orders'
    partitionKey: '/orderId'
  }
  {
    name: 'products'
    partitionKey: '/productId'
  }
]

resource cosmosDBContainers 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2020-04-01' = [for cosmosDBContainerDefinition in cosmosDBContainerDefinitions: {
  parent: cosmosDBDatabase
  name: cosmosDBContainerDefinition.name
  properties: {
    resource: {
      id: cosmosDBContainerDefinition.name
      partitionKey: {
        kind: 'Hash'
        paths: [
          cosmosDBContainerDefinition.partitionKey
        ]
      }
    }
    options: {}
  }
}]

Comment déployer des ressources dans certains environnements uniquement ?

Parfois, vous définissez des ressources à déployer uniquement dans des environnements spécifiques ou sous certaines conditions. En utilisant le mot clé if, vous pouvez déployer de manière sélective des ressources en fonction d’une valeur de paramètre, d’une variable de mappage de configuration ou d’une autre condition. L’exemple suivant utilise un mappage de configuration pour déployer des ressources de journalisation pour des environnements de production, mais pas pour des environnements de test :

var environmentConfigurationMap = {
  Production: {
    enableLogging: true
  }
  Test: {
    enableLogging: false
  }
}

resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-03-01-preview' = if (environmentConfigurationMap[environmentType].enableLogging) {
  name: logAnalyticsWorkspaceName
  location: location
}

resource cosmosDBAccountDiagnostics 'Microsoft.Insights/diagnosticSettings@2017-05-01-preview' = if (environmentConfigurationMap[environmentType].enableLogging) {
  scope: cosmosDBAccount
  name: cosmosDBAccountDiagnosticSettingsName
  properties: {
    workspaceId: logAnalyticsWorkspace.id
    // ...
  }
}

Comment exprimer les dépendances entre vos ressources ?

Dans un modèle Bicep complexe, vous devez exprimer les dépendances entre vos ressources. Quand Bicep comprend les dépendances entre vos ressources, il les déploie dans le bon ordre.

Bicep vous permet de spécifier explicitement une dépendance à l’aide de la propriété dependsOn. Cependant, dans la plupart des cas, il est possible de laisser Bicep détecter automatiquement les dépendances. Quand vous utilisez le nom symbolique d’une ressource dans une propriété d’une autre ressource, Bicep détecte la relation. Il est préférable de laisser Bicep les gérer dans la mesure du possible. Ainsi, quand vous modifiez votre modèle, Bicep vérifie que les dépendances sont toujours correctes et vous n’ajoutez pas de code inutile qui alourdit votre modèle et en complique la lecture.

Comment exprimer les relations parent-enfant ?

Azure Resource Manager et Bicep reconnaissent le concept de ressources enfants, qui n’est utile que lorsqu’elles sont déployées dans le contexte de leur parent. Par exemple, une base de données Azure SQL est un enfant d’une instance de serveur SQL. Il existe plusieurs façons de définir des ressources enfants, mais dans la plupart des cas, il est judicieux d’utiliser la propriété parent. Ceci permet à Bicep de comprendre la relation et de pouvoir valider dans Visual Studio Code, et cela rend aussi la relation claire pour toute personne qui lit le modèle.

Comment définir les propriétés des ressources ?

Il convient de spécifier les valeurs des propriétés des ressources dans vos fichiers Bicep. La prudence doit être de mise quand il s’agit de coder de manière irréversible les valeurs dans les définitions de ressources. Si vous savez que les valeurs ne changeront pas, il est peut-être préférable d’effectuer un codage de manière irréversible plutôt que d’utiliser un autre paramètre qui va rendre votre modèle plus difficile à tester et à utiliser. En revanche, si les valeurs sont susceptibles de changer, envisagez des les définir en tant que paramètres ou variables, votre code Bicep s’en trouvera plus dynamique et pour être réutilisé.

Quand vous codez les valeurs de manière irréversible, veillez à ce qu’elles soient compréhensibles. Par exemple, si une propriété doit avoir une valeur spécifique pour que la ressource se comporte correctement pour votre solution, vous pouvez créer une variable bien nommée qui fournit une explication, puis affecter la valeur en utilisant la variable. Si un nom de variable n’est pas suffisamment explicite, ajoutez un commentaire. Vous en apprendrez davantage sur les commentaires plus loin dans ce module.

Pour certaines propriétés de ressource, la construction automatique de valeurs passe par la création d’expressions complexes qui incluent des fonctions et l’interpolation de chaîne. Votre code Bicep est généralement plus clair lorsque vous déclarez des variables et que vous les référencez dans les blocs de code de ressources.

Conseil

Quand vous créez des sorties, essayez d’utiliser les propriétés de ressource partout où vous le pouvez. Évitez d’intégrer vos propres hypothèses sur le fonctionnement des ressources, car ces hypothèses peuvent changer au fil du temps.

Par exemple, si vous avez besoin de générer l’URL d’une application App Service, évitez de construire une URL :

output hostname string = '${app.name}.azurewebsites.net'

L’approche précédente ne va pas fonctionner si App Service change la façon d’affecter les noms d’hôte aux applications ou si vous déployez dans des environnements Azure qui utilisent des URL différentes.

À la place, utilisez la propriété defaultHostname de la ressource d’application :

output hostname string = app.properties.defaultHostname

Comment utiliser efficacement la gestion de version ?

Les systèmes de gestion de version comme Git peuvent vous simplifier la tâche quand vous refactorisez du code.

Comme les systèmes de gestion de version sont conçus pour assurer le suivi des modifications apportées à vos fichiers, vous pouvez les utiliser pour revenir facilement à une version antérieure de votre code si vous faites une erreur. Vous avez tout intérêt à valider régulièrement votre travail pour pouvoir revenir à un moment précis, si nécessaire.

La gestion de version vous permet aussi de supprimer le code ancien de vos fichiers Bicep. Et si votre code Bicep comporte une définition de ressource dont vous n’avez plus besoin ? Vous vous dites peut-être que vous risquez d’avoir de nouveau besoin de la définition dans l’avenir, et il est tentant de simplement la commenter et de la conserver dans le fichier. Mais en la conservant, vous allez encombrer votre fichier Bicep, et les utilisateurs ne comprendront pas pourquoi il existe toujours des ressources commentées.

Un autre point à prendre en considération est la possibilité que quelqu’un supprime accidentellement les marques de commentaire de la définition, avec des résultats imprévisibles ou potentiellement préjudiciables. Quand vous utilisez un système de gestion de version, vous pouvez simplement supprimer l’ancienne définition de la ressource. Si vous avez à nouveau besoin de la définition par la suite, vous pouvez la récupérer dans l’historique des fichiers.