Comparación de JSON y Bicep para plantillas

En este artículo se compara la sintaxis de Bicep con la sintaxis de JSON para las plantillas de Azure Resource Manager (plantillas de ARM). En la mayoría de los casos, Bicep proporciona una sintaxis menos detallada que el equivalente en JSON.

Si ya tiene experiencia con JSON para desarrollar plantillas de ARM, use los siguientes ejemplos para obtener información sobre los equivalentes de sintaxis para Bicep.

Comparación de archivos completos

Bicep Playground permite ver el archivo Bicep y el archivo JSON equivalente en paralelo. Es posible comparar las implementaciones de la misma infraestructura.

Por ejemplo, puede ver el archivo para implementar un servidor y una base de datos SQL. El tamaño del archivo Bicep es aproximadamente la mitad de la plantilla ARM.

Captura de pantalla de plantillas en paralelo

Expresiones

Para crear una expresión:

func()
"[func()]"

Parámetros

Para declarar un parámetro con un valor predeterminado:

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

Para obtener un valor de parámetro, use el nombre que ha definido:

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

variables

Para declarar una variable:

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

Para obtener un valor de variable, use el nombre que ha definido:

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

Cadenas

Para concatenar cadenas:

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

Operadores lógicos

Para devolver el operador AND lógico:

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

Para establecer un valor de forma condicional:

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

Ámbito de la implementación

Para establecer el ámbito de destino de la implementación:

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

Recursos

Para declarar un recurso:

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

Para implementar un recurso de forma condicional:

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

Para establecer una propiedad de un recurso:

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

Para obtener el identificador de un recurso en la plantilla:

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

Bucles

Para recorrer en iteración los elementos de una matriz o un recuento:

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

Dependencias de recursos

Para Bicep, puede establecer una dependencia explícita, pero no se recomienda este enfoque. En su lugar, use las dependencias implícitas. Se crea una dependencia implícita cuando una declaración de recursos hace referencia al identificador de otro recurso.

A continuación, se muestra una interfaz de red con una dependencia implícita en un grupo de seguridad de red. Hace referencia al grupo de seguridad de red con 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 debe establecer una dependencia explícita, use:

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

Recursos de referencia

Para obtener una propiedad de un recurso de la plantilla:

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

Para obtener una propiedad de un recurso existente que no está implementado en la plantilla:

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]"

En Bicep, use el descriptor de acceso anidado (::) para obtener una propiedad en un recurso anidado dentro de un recurso primario:

VNet1::Subnet1.properties.addressPrefix

Para JSON, use la función de referencia:

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

Salidas

Para enviar la salida de una propiedad de un recurso de la plantilla:

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

Para generar condicionalmente un valor:

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]"
  }
}

El operador ternario de Bicep es el equivalente a la función if de un JSON de plantilla de ARM, no la propiedad condition. La sintaxis ternaria tiene que evaluarse en un valor u otro. Si la condición es falsa en las muestras anteriores, Bicep genera un nombre de host con una cadena vacía, pero JSON no genera ningún valor.

Reutilización del código

Para dividir una solución en varios archivos:

Pasos siguientes