Comparar JSON e Bicep para modelos

Este artigo compara a sintaxe Bicep com a sintaxe JSON para modelos do Azure Resource Manager (modelos do ARM). Na maioria dos casos, o Bicep fornece uma sintaxe menos detalhada do que o equivalente em JSON.

Se estiver familiarizado com o uso de JSON para desenvolver modelos do ARM, use os exemplos a seguir para aprender sobre a sintaxe equivalente para Bicep.

Comparar arquivos completos

O Playground do Bicep permite exibir o Bicep e o JSON equivalente lado a lado. É possível comparar as implementações da mesma infraestrutura.

Por exemplo, você pode exibir o arquivo para implantar um servidor SQL e banco de dados. O Bicep tem cerca de metade do tamanho do modelo do ARM.

Captura de tela de modelos lado a lado

Expressões

Para criar uma expressão de linguagem:

func()
"[func()]"

Parâmetros

Para declarar um parâmetro com um valor padrão:

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

Para obter um valor de parâmetro, use o nome que você definiu:

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

Variáveis

Para declarar uma variável:

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

Para obter um valor de variável, use o nome que você definiu:

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

Cadeias de caracteres

Para concatenar cadeias de caracteres:

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

Operadores lógicos

Para retornar a lógica AND:

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

Para definir um valor condicionalmente:

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

Escopo da implantação

Para definir o escopo de destino da implantação:

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

Recursos

Para declarar um recurso:

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

Para implantar um recurso condicionalmente:

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

Para definir uma propriedade de recurso:

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

Para obter a ID do recurso de um recurso no modelo:

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

Loops

Para iterar itens em uma matriz ou contagem:

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

Dependências de recursos

Para Bicep, é possível definir uma dependência explícita, mas essa abordagem não é recomendada. Em vez disso, use dependências implícitas. Uma dependência implícita é criada quando uma declaração de recurso referencia o identificador de outro recurso.

A seguir, é apresentada uma interface de rede com uma dependência implícita em um grupo de segurança de rede. Referencia o grupo de segurança de rede com 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
    }
  }
}

Se for necessário definir uma dependência explícita, use:

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

Recursos de referência

Para obter uma propriedade de um recurso no modelo:

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

Para obter uma propriedade de um recurso existente que não foi implantado no modelo:

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

No bicep, use o acessador aninhado ( :: ) para obter uma propriedade em um recurso aninhado em um recurso pai:

VNet1::Subnet1.properties.addressPrefix

Para JSON, use a função de referência:

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

Saídas

Para gerar uma propriedade de um recurso no modelo:

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

Para gerar a saída de um valor de modo condicional:

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

O operador ternário Bicep é equivalente à função if em um JSON de modelo do ARM, não à propriedade de condição. A sintaxe de ternário deve ser avaliada como um valor ou outro. Se a condição for falsa nos exemplos anteriores, o Bicep gerará um nome do host com uma cadeia de caracteres vazia, mas o JSON não gerará nenhum valor.

Reutilização de código

Para separar uma solução em vários arquivos:

Próximas etapas