Comparaison de JSON et Bicep pour les modèles

Cet article compare les syntaxes Bicep et JSON pour les modèles Azure Resource Manager (modèles ARM). Dans la plupart des cas, Bicep fournit une syntaxe moins détaillée que l’équivalent dans JSON.

Si vous êtes familiarisé avec l’utilisation de JSON pour développer des modèles ARM, utilisez les exemples suivants pour découvrir la syntaxe équivalente pour Bicep.

Comparer des fichiers complets

Le Terrain de jeu Bicep vous permet d’afficher côte à côte un fichier Bicep et son équivalent JSON. Vous pouvez comparer les implémentations de la même infrastructure.

Par exemple, vous pouvez afficher le fichier pour déployer un serveur et une base de données SQL. Bicep fait environ la moitié de la taille du modèle ARM.

Capture d’écran de modèles côte à côte

Expressions

Pour créer une expression :

func()
"[func()]"

Paramètres

Pour déclarer un paramètre avec une valeur par défaut :

param orgName string = 'Contoso'
"parameters": {
  "orgName": {
    "type": "string",
    "defaultValue": "Contoso"
  }
}

Pour obtenir une valeur de paramètre, utilisez le nom que vous avez défini :

name: orgName
"name": "[parameters('orgName'))]"

Variables

Pour déclarer une variable :

var description = 'example value'
"variables": {
  "description": "example value"
},

Pour obtenir une valeur de variable, utilisez le nom que vous avez défini :

workloadSetting: description
"workloadSetting": "[variables('description'))]"

Chaînes

Pour concaténer des chaînes :

name: '${namePrefix}-vm'
"name": "[concat(parameters('namePrefix'), '-vm')]"

Opérateurs logiques

Pour retourner l’opérateur logique AND :

isMonday && isNovember
[and(parameter('isMonday'), parameter('isNovember'))]

Pour définir une valeur de manière conditionnelle :

isMonday ? 'valueIfTrue' : 'valueIfFalse'
[if(parameters('isMonday'), 'valueIfTrue', 'valueIfFalse')]

Étendue du déploiement

Pour définir l’étendue cible du déploiement :

targetScope = 'subscription'
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#"

Ressources

Pour déclarer une ressource :

resource virtualMachine 'Microsoft.Compute/virtualMachines@2023-03-01' = {
  ...
}
"resources": [
  {
    "type": "Microsoft.Compute/virtualMachines",
    "apiVersion": "2020-06-01",
    ...
  }
]

Pour déployer une ressource de manière conditionnelle :

resource virtualMachine 'Microsoft.Compute/virtualMachines@2023-03-01' = if(deployVM) {
  ...
}
"resources": [
  {
    "condition": "[parameters('deployVM')]",
    "type": "Microsoft.Compute/virtualMachines",
    "apiVersion": "2023-03-01",
    ...
  }
]

Pour définir une propriété de ressource :

sku: '2016-Datacenter'
"sku": "2016-Datacenter",

Pour obtenir l’ID d’une ressource dans un modèle :

nic1.id
[resourceId('Microsoft.Network/networkInterfaces', variables('nic1Name'))]

Boucles

Pour itérer au sein des éléments d’un tableau ou d’un total :

[for storageName in storageAccountNames: {
  ...
}]
"copy": {
  "name": "storagecopy",
  "count": "[length(parameters('storageAccountNames'))]"
},
...

Dépendances des ressources

Pour Bicep, vous pouvez définir une dépendance explicite, mais cette approche n’est pas recommandée. En revanche, reposez-vous sur les dépendances implicites. Une dépendance implicite est créée lorsqu’une déclaration de ressource référence l’identificateur d’une autre ressource.

L’exemple suivant montre une interface réseau avec une dépendance implicite sur un groupe de sécurité réseau. Il fait référence au groupe de sécurité réseau avec netSecurityGroup.id.

resource netSecurityGroup 'Microsoft.Network/networkSecurityGroups@2022-11-01' = {
  ...
}

resource nic1 'Microsoft.Network/networkInterfaces@2022-11-01' = {
  name: nic1Name
  location: location
  properties: {
    ...
    networkSecurityGroup: {
      id: netSecurityGroup.id
    }
  }
}

Si vous devez définir une dépendance explicite, utilisez :

dependsOn: [ storageAccount ]
"dependsOn": ["[resourceId('Microsoft.Storage/storageAccounts', 'parameters('storageAccountName'))]"]

Ressources de référence

Pour obtenir une propriété à partir d’une ressource dans le modèle :

storageAccount.properties.primaryEndpoints.blob
[reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))).primaryEndpoints.blob]

Pour obtenir une propriété d’une ressource existante qui n’est pas déployée dans le modèle :

resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' existing = {
  name: storageAccountName
}

// use later in template as often as needed
storageAccount.properties.primaryEndpoints.blob
// required every time the property is needed
"[reference(resourceId('Microsoft.Storage/storageAccounts/', parameters('storageAccountName')), '2019-06-01').primaryEndpoints.blob]"

Dans Bicep, utilisez l’accesseur imbriqué (::) pour obtenir une propriété sur une ressource imbriquée dans une ressource parente :

VNet1::Subnet1.properties.addressPrefix

Pour JSON, utilisez la fonction de référence :

[reference(resourceId('Microsoft.Network/virtualNetworks/subnets', variables('subnetName'))).properties.addressPrefix]

Sorties

Pour sortir une propriété d’une ressource dans le modèle :

output hostname string = publicIP.properties.dnsSettings.fqdn
"outputs": {
  "hostname": {
    "type": "string",
    "value": "[reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))).dnsSettings.fqdn]"
  },
}

Pour sortir une valeur soit de manière conditionnelle :

output hostname string = condition ? publicIP.properties.dnsSettings.fqdn : ''
"outputs": {
  "hostname": {
    "condition": "[variables('condition')]",
    "type": "string",
    "value": "[reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))).dnsSettings.fqdn]"
  }
}

L’opérateur ternaire Bicep est l’équivalent de la fonction if dans un JSON de modèle ARM, et non la propriété de condition. La syntaxe de l’opérateur ternaire doit prendre une valeur ou l’autre. Si la condition est fausse dans les exemples précédents, Bicep produit un nom d’hôte avec une chaîne vide, mais JSON ne produit aucune valeur.

Réutilisation du code

Pour scinder une solution en plusieurs fichiers :

Étapes suivantes