Dela via


Iterativa loopar i Bicep

Den här artikeln visar hur du använder syntaxen for för att iterera över objekt i en samling. Den här funktionen stöds från och med v0.3.1. Du kan använda loopar för att definiera flera kopior av en resurs, modul, variabel, egenskap eller utdata. Använd loopar för att undvika upprepad syntax i Bicep-filen och för att dynamiskt ange antalet kopior som ska skapas under distributionen. Se Snabbstart: Skapa flera resursinstanser i Bicep för en snabbstart av hur du använder olika for syntaxer för att skapa flera resursinstanser i Bicep.

Om du vill använda loopar för att skapa flera resurser eller moduler måste varje instans ha ett unikt värde för name egenskapen. Du kan använda indexvärdet eller unika värden i matriser eller samlingar för att skapa namnen.

Utbildningsresurser

Stegvis vägledning om loopar finns i modulen Skapa flexibla Bicep-filer med hjälp av villkor och loopar i Microsoft Learn.

Loop-syntax

Loopar kan deklareras genom:

  • Använda ett heltalsindex. Det här alternativet fungerar när ditt scenario är: "Jag vill skapa så här många instanser." Intervallfunktionen skapar en matris med heltal som börjar vid startindexet och innehåller antalet angivna element. I loopen kan du använda heltalsindexet för att ändra värden. Mer information finns i Heltalsindex.

    [for <index> in range(<startIndex>, <numberOfElements>): {
      ...
    }]
    
  • Använda objekt i en matris: Det här alternativet fungerar när scenariot är "Jag vill skapa en instans för varje element i en matris". I loopen kan du använda värdet för det aktuella matriselementet för att ändra värden. Mer information finns i Matriselement.

    [for <item> in <collection>: {
      ...
    }]
    
  • Använda objekt i ett ordlisteobjekt: Det här alternativet fungerar när scenariot är "Jag vill skapa en instans för varje objekt i ett objekt". Objektfunktionen konverterar objektet till en matris. I loopen kan du använda egenskaper från objektet för att skapa värden. Mer information finns i Ordlisteobjekt.

    [for <item> in items(<object>): {
      ...
    }]
    
  • Använda heltalsindex och objekt i en matris: Det här alternativet fungerar när scenariot är " Jag vill skapa en instans för varje element i en matris, men jag behöver också det aktuella indexet för att skapa ett annat värde." Mer information finns i Loopmatris och index.

    [for (<item>, <index>) in <collection>: {
      ...
    }]
    
  • Lägga till en villkorsstyrd distribution: Det här alternativet fungerar när ditt scenario är" Jag vill skapa flera instanser, men jag vill bara distribuera varje instans när ett villkor är sant." Mer information finns i Loopa med villkor.

    [for <item> in <collection>: if(<condition>) {
      ...
    }]
    

Loopgränser

Att använda loopar i Bicep har följande begränsningar:

  • Bicep-loopar fungerar bara med värden som kan fastställas i början av distributionen.
  • Loop-iterationer kan inte vara ett negativt tal eller överskrida 800 iterationer.
  • Eftersom en resurs inte kan loopa med kapslade underordnade resurser ändrar du de underordnade resurserna till resurser på den översta nivån. Mer information finns i Iteration för en underordnad resurs.
  • Om du vill loopa på flera egenskapsnivåer använder du lambda-funktionenmap.

Heltalsindex

Ett enkelt exempel på hur du använder ett index är att skapa en variabel som innehåller en matris med strängar:

param itemCount int = 5

var stringArray = [for i in range(0, itemCount): 'item${(i + 1)}']

output arrayResult array = stringArray

Utdata returnerar en matris med följande värden:

[
  "item1",
  "item2",
  "item3",
  "item4",
  "item5"
]

I nästa exempel skapas det antal lagringskonton som anges i parametern storageCount . Den returnerar tre egenskaper för varje lagringskonto:

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

Observera att indexet i används för att skapa lagringskontots resursnamn.

I nästa exempel distribueras en modul flera gånger:

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

Vektorelement

I följande exempel skapas ett lagringskonto för varje namn som anges i parametern storageNames . Observera att namnegenskapen för varje resursinstans måste vara unik:

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

Nästa exempel itererar över en matris för att definiera en egenskap. Det skapar två undernät i ett virtuellt nätverk. Observera att undernätsnamnen måste vara unika:

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

Matris och index

I följande exempel används både matriselementet och indexvärdet när du definierar lagringskontot:

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

I nästa exempel används både elementen i en matris och ett index för att mata ut information om de nya resurserna:

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

Ordlisteobjekt

Om du vill iterera över element i ett ordlisteobjekt använder du items funktionen som konverterar objektet till en matris. Använd egenskapen value för att hämta egenskaper för objekten. Observera att nsg-resursnamnen måste vara unika.

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 med villkor

För resurser och moduler kan du lägga till ett if uttryck med loopsyntaxen för att villkorligt distribuera samlingen.

I följande exempel visas en loop som kombineras med en villkorssats. I det här exemplet tillämpas ett enda villkor på alla instanser av modulen:

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

I nästa exempel visas hur du tillämpar ett villkor som är specifikt för det aktuella elementet i matrisen:

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

Distribuera i omgångar

Azure-resurser distribueras parallellt som standard. När du använder en loop för att skapa flera instanser av en resurstyp distribueras alla dessa instanser samtidigt. Ordningen som de skapas i är inte garanterad. Det finns ingen gräns för antalet resurser som distribueras parallellt än den totala gränsen på 800 resurser i Bicep-filen.

Du kanske inte vill uppdatera alla instanser av en resurstyp samtidigt. När du till exempel uppdaterar en produktionsmiljö kanske du vill flytta uppdateringarna så att endast ett visst antal uppdateras samtidigt. Du kan ange att en delmängd av instanserna ska batchas ihop och distribueras samtidigt. De andra instanserna väntar på att batchen ska slutföras.

Om du vill distribuera instanser av en resurs seriellt lägger du till dekoratörenbatchSize. Ange dess värde till antalet instanser som ska distribueras samtidigt. Ett beroende skapas under tidigare instanser i loopen, så det startar inte en batch förrän föregående batch har slutförts.

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

För sekventiell distribution anger du batchstorleken till 1.

Dekoratören batchSize finns i sys-namnområdet. Om du behöver skilja den här dekoratören från ett annat objekt med samma namn, förorda dekoratören med sys: @sys.batchSize(2)

Iteration för en barnresurs

Om du vill skapa fler än en instans av en underresurs stöder bägge följande Bicep-filer den här uppgiften:

Kapslade barnresurser

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

Underordnade resurser på toppnivå

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

Referensresurs-/modulsamlingar

Funktionen Azure Resource Manager-mall (ARM-mall) references returnerar en matris med objekt som representerar en resurssamlings körningstillstånd. Eftersom det inte finns någon explicit references funktion i Bicep och symbolisk samlingsanvändning används direkt översätter Bicep den till en ARM-mall som använder ARM-mallfunktionen references medan koden genererar. För översättningsfunktionen som använder references funktionen för att omvandla symboliska samlingar till ARM-mallar är det nödvändigt att ha Bicep CLI version 0.20.X eller senare. I filenbicepconfig.jsonsymbolicNameCodegen ska inställningen dessutom visas och anges till true.

Utdata från de två exemplen i Heltalsindex kan skrivas som:

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)

Den här Bicep-filen överförs till följande ARM JSON-mall som använder references funktionen:

{
  "$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))]"
    }
  }
}

Observera i föregående ARM JSON-mall, languageVersion måste anges till 1.10-experimental, och resurselementet är ett objekt i stället för en matris.

Nästa steg

Information om hur du skapar Bicep-filer finns i Bicep-filstruktur och syntax.