Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este artigo mostra como usar a sintaxe for
para iterar sobre itens numa coleção. Esta funcionalidade é suportada a partir da v0.3.1. Você pode usar loops para definir várias cópias de um recurso, módulo, variável, propriedade ou saída. Use loops para evitar a repetição da sintaxe no arquivo Bicep e para definir dinamicamente o número de cópias a serem criadas durante a implantação. Consulte Guia de início rápido: criar várias instâncias de recursos no Bicep para obter um início rápido de como usar sintaxes diferentes for
para criar várias instâncias de recursos no Bicep.
Para usar loops para criar vários recursos ou módulos, cada instância deve ter um valor exclusivo para a name
propriedade. Você pode usar o valor de índice ou valores exclusivos em matrizes ou coleções para criar os nomes.
Recursos de formação
Para obter orientação passo a passo sobre loops, consulte o módulo Criar arquivos Bicep flexíveis usando condições e loops no Microsoft Learn.
Sintaxe de ciclo
Os loops podem ser declarados por:
Usando um índice inteiro. Essa opção funciona quando o cenário é: "Quero criar tantas instâncias". A função range cria uma matriz de inteiros que começa no índice inicial e contém o número de elementos especificados. Dentro do loop, você pode usar o índice inteiro para modificar valores. Para obter mais informações, consulte Índice inteiro.
[for <index> in range(<startIndex>, <numberOfElements>): { ... }]
Usando itens em uma matriz: essa opção funciona quando o cenário é "Quero criar uma instância para cada elemento em uma matriz". Dentro do loop, você pode usar o valor do elemento de matriz atual para modificar valores. Para obter mais informações, consulte Elementos de matriz.
[for <item> in <collection>: { ... }]
Usando itens em um objeto de dicionário: essa opção funciona quando o cenário é "Quero criar uma instância para cada item em um objeto". A função items converte o objeto em uma matriz. Dentro do loop, você pode usar propriedades do objeto para criar valores. Para obter mais informações, consulte Objeto de dicionário.
[for <item> in items(<object>): { ... }]
Usando índice inteiro e itens em uma matriz: essa opção funciona quando o cenário é: "Quero criar uma instância para cada elemento em uma matriz, mas também preciso do índice atual para criar outro valor". Para obter mais informações, consulte Matriz de loop e índice.
[for (<item>, <index>) in <collection>: { ... }]
Adicionando uma implantação condicional: essa opção funciona quando o cenário é "Quero criar várias instâncias, mas só quero implantar cada instância quando uma condição for verdadeira". Para obter mais informações, consulte Loop with condition.
[for <item> in <collection>: if(<condition>) { ... }]
Limites de ciclo
O uso de loops no Bicep tem estas limitações:
- Os laços de bíceps só funcionam com valores que podem ser definidos no início da implantação.
- As iterações de loop não podem ser um número negativo ou exceder 800 iterações.
- Como um recurso não pode fazer loop com recursos filho aninhados, altere os recursos filho para recursos de nível superior. Para obter mais informações, consulte Iteração para um recurso filho.
- Para fazer loop em vários níveis de propriedade, use a função lambda
map
.
Índice inteiro
Para obter um exemplo simples de uso de um índice, crie uma variável que contenha uma matriz de cadeias de caracteres:
param itemCount int = 5
var stringArray = [for i in range(0, itemCount): 'item${(i + 1)}']
output arrayResult array = stringArray
A saída retorna uma matriz com os seguintes valores:
[
"item1",
"item2",
"item3",
"item4",
"item5"
]
O próximo exemplo cria o número de contas de armazenamento especificadas no storageCount
parâmetro. Ele retorna três propriedades para cada conta de armazenamento:
param ___location string = resourceGroup().___location
param storageCount int = 2
resource storageAcct 'Microsoft.Storage/storageAccounts@2023-05-01' = [for i in range(0, storageCount): {
name: '${i}storage${uniqueString(resourceGroup().id)}'
___location: ___location
sku: {
name: 'Standard_LRS'
}
kind: 'Storage'
}]
output storageInfo array = [for i in range(0, storageCount): {
id: storageAcct[i].id
blobEndpoint: storageAcct[i].properties.primaryEndpoints.blob
status: storageAcct[i].properties.statusOfPrimary
}]
Observe que o índice i
é usado na criação do nome do recurso da conta de armazenamento.
O próximo exemplo implanta um módulo várias vezes:
param ___location string = resourceGroup().___location
param storageCount int = 2
var baseName = 'store${uniqueString(resourceGroup().id)}'
module stgModule './storageAccount.bicep' = [for i in range(0, storageCount): {
name: '${i}deploy${baseName}'
params: {
storageName: '${i}${baseName}'
___location: ___location
}
}]
output storageAccountEndpoints array = [for i in range(0, storageCount): {
endpoint: stgModule[i].outputs.storageEndpoint
}]
Elementos de matriz
O exemplo a seguir cria uma conta de armazenamento para cada nome fornecido no storageNames
parâmetro. Observe que a propriedade nome para cada instância de recurso deve ser única.
param ___location string = resourceGroup().___location
param storageNames array = [
'contoso'
'fabrikam'
'coho'
]
resource storageAcct 'Microsoft.Storage/storageAccounts@2023-05-01' = [for name in storageNames: {
name: '${name}${uniqueString(resourceGroup().id)}'
___location: ___location
sku: {
name: 'Standard_LRS'
}
kind: 'Storage'
}]
O próximo exemplo itera sobre uma matriz para definir uma propriedade. Ele cria duas sub-redes dentro de uma rede virtual. Observe que os nomes das sub-redes devem ser exclusivos:
param rgLocation string = resourceGroup().___location
var subnets = [
{
name: 'api'
subnetPrefix: '10.144.0.0/24'
}
{
name: 'worker'
subnetPrefix: '10.144.1.0/24'
}
]
resource vnet 'Microsoft.Network/virtualNetworks@2023-11-01' = {
name: 'vnet'
___location: rgLocation
properties: {
addressSpace: {
addressPrefixes: [
'10.144.0.0/20'
]
}
subnets: [for subnet in subnets: {
name: subnet.name
properties: {
addressPrefix: subnet.subnetPrefix
}
}]
}
}
Matriz e índice
O exemplo a seguir usa o elemento array e o valor de índice ao definir a conta de armazenamento:
param storageAccountNamePrefix string
var storageConfigurations = [
{
suffix: 'local'
sku: 'Standard_LRS'
}
{
suffix: 'geo'
sku: 'Standard_GRS'
}
]
resource storageAccountResources 'Microsoft.Storage/storageAccounts@2023-05-01' = [for (config, i) in storageConfigurations: {
name: '${storageAccountNamePrefix}${config.suffix}${i}'
___location: resourceGroup().___location
sku: {
name: config.sku
}
kind: 'StorageV2'
}]
O próximo exemplo usa os elementos de uma matriz e um índice para gerar informações sobre os novos recursos:
param ___location string = resourceGroup().___location
param orgNames array = [
'Contoso'
'Fabrikam'
'Coho'
]
resource nsg 'Microsoft.Network/networkSecurityGroups@2023-11-01' = [for name in orgNames: {
name: 'nsg-${name}'
___location: ___location
}]
output deployedNSGs array = [for (name, i) in orgNames: {
orgName: name
nsgName: nsg[i].name
resourceId: nsg[i].id
}]
Objeto de dicionário
Para iterar sobre elementos em um objeto de dicionário, use a items
função, que converte o objeto em uma matriz. Use a propriedade value
para obter propriedades dos objetos. Observe que os nomes de recursos nsg devem ser exclusivos.
param nsgValues object = {
nsg1: {
name: 'nsg-westus1'
___location: 'westus'
}
nsg2: {
name: 'nsg-east1'
___location: 'eastus'
}
}
resource nsg 'Microsoft.Network/networkSecurityGroups@2023-11-01' = [for nsg in items(nsgValues): {
name: nsg.value.name
___location: nsg.value.___location
}]
Loop com condição
Para recursos e módulos, você pode adicionar uma if
expressão com a sintaxe de loop para implantar condicionalmente a coleção.
O exemplo a seguir mostra um loop combinado com uma instrução condicional. Neste exemplo, uma única condição é aplicada a todas as instâncias do módulo:
param ___location string = resourceGroup().___location
param storageCount int = 2
param createNewStorage bool = true
var baseName = 'store${uniqueString(resourceGroup().id)}'
module stgModule './storageAccount.bicep' = [for i in range(0, storageCount): if(createNewStorage) {
name: '${i}deploy${baseName}'
params: {
storageName: '${i}${baseName}'
___location: ___location
}
}]
O próximo exemplo mostra como aplicar uma condição específica ao elemento atual na matriz:
resource parentResources 'Microsoft.Example/examples@2024-06-06' = [for parent in parents: if(parent.enabled) {
name: parent.name
properties: {
children: [for child in parent.children: {
name: child.name
setting: child.settingValue
}]
}
}]
Implantar em lotes
Os recursos do Azure são implantados em paralelo por padrão. Quando você usa um loop para criar várias instâncias de um tipo de recurso, essas instâncias são todas implantadas ao mesmo tempo. A ordem em que são criados não é garantida. Não há um limite para o número de recursos implantados em paralelo além do limite total de 800 recursos no arquivo Bicep.
Talvez você não queira atualizar todas as instâncias de um tipo de recurso ao mesmo tempo. Por exemplo, ao atualizar um ambiente de produção, convém escalonar as atualizações para apenas um determinado número a ser atualizado a qualquer momento. Você pode especificar para um subconjunto das instâncias a serem agrupadas em lote e implantadas ao mesmo tempo. As outras instâncias aguardam a conclusão desse lote.
Para implantar instâncias em série de um recurso, adicione o batchSize
decorador. Defina seu valor para o número de instâncias a serem implantadas simultaneamente. Uma dependência é criada durante instâncias anteriores no loop, portanto, ela não inicia um lote até que o lote anterior seja concluído.
param ___location string = resourceGroup().___location
@batchSize(2)
resource storageAcct 'Microsoft.Storage/storageAccounts@2023-05-01' = [for i in range(0, 4): {
name: '${i}storage${uniqueString(resourceGroup().id)}'
___location: ___location
sku: {
name: 'Standard_LRS'
}
kind: 'Storage'
}]
Para implantação sequencial, defina o tamanho do lote como 1.
O batchSize
decorador está no espaço de nomes sys. Se você precisa diferenciar este decorador de outro item com o mesmo nome, prefacie o decorador com sys: @sys.batchSize(2)
Iteração para um recurso filho
Para criar mais de uma instância de um recurso filho, ambos os seguintes arquivos Bicep oferecem suporte a essa tarefa:
Recursos filho aninhados
param ___location string = resourceGroup().___location
resource stg 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: 'examplestorage'
___location: ___location
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
resource service 'fileServices' = {
name: 'default'
resource share 'shares' = [for i in range(0, 3): {
name: 'exampleshare${i}'
}]
}
}
Recursos filho de nível superior
resource stg 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: 'examplestorage'
___location: resourceGroup().___location
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
}
resource service 'Microsoft.Storage/storageAccounts/fileServices@2023-05-01' = {
name: 'default'
parent: stg
}
resource share 'Microsoft.Storage/storageAccounts/fileServices/shares@2023-05-01' = [for i in range(0, 3): {
name: 'exampleshare${i}'
parent: service
}]
Coleções de recursos/módulos de referência
A função de modelo do Azure Resource Manager (modelo ARM) references
retorna uma matriz de objetos que representam os estados de tempo de execução de uma coleção de recursos. Como não há uma função explícita references
no Bicep e o uso da coleção simbólica é empregado diretamente, o Bicep traduz para um modelo de ARM que utiliza a função references
do modelo ARM durante a geração de código. Para o recurso de tradução que usa a função references
para transformar coleções simbólicas em modelos ARM, é necessário ter a versão 0.20.X ou superior da CLI do Bicep. Além disso, no arquivo bicepconfig.json , a symbolicNameCodegen
configuração deve ser apresentada e definida como true
.
As saídas dos dois exemplos no índice inteiro podem ser escritas como:
param ___location string = resourceGroup().___location
param storageCount int = 2
resource storageAcct 'Microsoft.Storage/storageAccounts@2023-05-01' = [for i in range(0, storageCount): {
name: '${i}storage${uniqueString(resourceGroup().id)}'
___location: ___location
sku: {
name: 'Standard_LRS'
}
kind: 'Storage'
}]
output storageInfo array = map(storageAcct, store => {
blobEndpoint: store.properties.primaryEndpoints
status: store.properties.statusOfPrimary
})
output storageAccountEndpoints array = map(storageAcct, store => store.properties.primaryEndpoints)
Este arquivo Bicep é transpilado no seguinte modelo ARM JSON que utiliza a função references
.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"languageVersion": "1.10-experimental",
"contentVersion": "1.0.0.0",
"parameters": {
"___location": {
"type": "string",
"defaultValue": "[resourceGroup().___location]"
},
"storageCount": {
"type": "int",
"defaultValue": 2
}
},
"resources": {
"storageAcct": {
"copy": {
"name": "storageAcct",
"count": "[length(range(0, parameters('storageCount')))]"
},
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2023-04-01",
"name": "[format('{0}storage{1}', range(0, parameters('storageCount'))[copyIndex()], uniqueString(resourceGroup().id))]",
"___location": "[parameters('___location')]",
"sku": {
"name": "Standard_LRS"
},
"kind": "Storage"
}
},
"outputs": {
"storageInfo": {
"type": "array",
"value": "[map(references('storageAcct', 'full'), lambda('store', createObject('blobEndpoint', lambdaVariables('store').properties.primaryEndpoints, 'status', lambdaVariables('store').properties.statusOfPrimary)))]"
},
"storageAccountEndpoints": {
"type": "array",
"value": "[map(references('storageAcct', 'full'), lambda('store', lambdaVariables('store').properties.primaryEndpoints))]"
}
}
}
Observação no modelo JSON ARM anterior, languageVersion
deve ser definido como 1.10-experimental
, e o elemento resource é um objeto em vez de uma matriz.
Próximos passos
Para saber como criar arquivos Bicep, consulte Sintaxe e estrutura de arquivos Bicep.