Iteratieve lussen in Bicep

In dit artikel leest u hoe u de for syntaxis gebruikt om items in een verzameling te herhalen. Deze functionaliteit wordt ondersteund vanaf v0.3.1. U kunt lussen gebruiken om meerdere kopieën van een resource, module, variabele, eigenschap of uitvoer te definiëren. Gebruik lussen om herhalingssyntaxis in uw Bicep-bestand te voorkomen en om het aantal kopieën dat tijdens de implementatie moet worden gemaakt dynamisch in te stellen. Zie Quickstart: Meerdere exemplaren maken om een quickstart te doorlopen.

Als u lussen wilt gebruiken om meerdere resources of modules te maken, moet elk exemplaar een unieke waarde hebben voor de naameigenschap. U kunt de indexwaarde of unieke waarden in matrices of verzamelingen gebruiken om de namen te maken.

Trainingsmateriaal

Als u liever meer wilt weten over stapsgewijze instructies, raadpleegt u Flexibele Bicep-sjablonen bouwen met behulp van voorwaarden en lussen.

Lussyntaxis

Lussen kunnen worden gedeclareerd door:

  • Een geheel getal index gebruiken. Deze optie werkt wanneer uw scenario is: 'Ik wil dit aantal exemplaren maken'. Met de bereikfunctie maakt u een matrix met gehele getallen die beginnen bij de beginindex en het aantal opgegeven elementen bevat. Binnen de lus kunt u de index voor gehele getallen gebruiken om waarden te wijzigen. Zie Integer-index voor meer informatie.

    [for <index> in range(<startIndex>, <numberOfElements>): {
      ...
    }]
    
  • Items in een matrix gebruiken. Deze optie werkt wanneer uw scenario is: 'Ik wil een exemplaar maken voor elk element in een matrix'. Binnen de lus kunt u de waarde van het huidige matrixelement gebruiken om waarden te wijzigen. Zie Matrixelementen voor meer informatie.

    [for <item> in <collection>: {
      ...
    }]
    
  • Items in een woordenlijstobject gebruiken. Deze optie werkt wanneer uw scenario is: 'Ik wil een exemplaar maken voor elk item in een object'. Met de functie Items wordt het object geconverteerd naar een matrix. Binnen de lus kunt u eigenschappen van het object gebruiken om waarden te maken. Zie Woordenboekobject voor meer informatie.

    [for <item> in items(<object>): {
      ...
    }]
    
  • Het gebruik van een geheel getalindex en items in een matrix. Deze optie werkt als uw scenario is: 'Ik wil een exemplaar maken voor elk element in een matrix, maar ik heb ook de huidige index nodig om een andere waarde te maken.' Zie Loopmatrix en index voor meer informatie.

    [for (<item>, <index>) in <collection>: {
      ...
    }]
    
  • Een voorwaardelijke implementatie toevoegen. Deze optie werkt wanneer uw scenario is: 'Ik wil meerdere exemplaren maken, maar voor elk exemplaar dat ik alleen wil implementeren wanneer aan een voorwaarde wordt voldaan'. Zie Lus met voorwaarde voor meer informatie.

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

Luslimieten

Het gebruik van lussen in Bicep heeft deze beperkingen:

  • Bicep-lussen werken alleen met waarden die aan het begin van de implementatie kunnen worden bepaald.
  • Herhalingen van lussen kunnen geen negatief getal zijn of meer dan 800 iteraties zijn.
  • Kan een resource niet herhalen met geneste onderliggende resources. Wijzig de onderliggende resources in resources op het hoogste niveau. Zie Iteratie voor een onderliggende resource.
  • Als u meerdere niveaus van eigenschappen wilt herhalen, gebruikt u de lambda-kaartfunctie.

Index geheel getal

Voor een eenvoudig voorbeeld van het gebruik van een index maakt u een variabele die een matrix met tekenreeksen bevat.

param itemCount int = 5

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

output arrayResult array = stringArray

De uitvoer retourneert een matrix met de volgende waarden:

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

In het volgende voorbeeld wordt het aantal opslagaccounts gemaakt dat is opgegeven in de storageCount parameter. Het retourneert drie eigenschappen voor elk opslagaccount.

param location string = resourceGroup().location
param storageCount int = 2

resource storageAcct 'Microsoft.Storage/storageAccounts@2022-09-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
}]

U ziet dat de index i wordt gebruikt bij het maken van de resourcenaam van het opslagaccount.

In het volgende voorbeeld wordt een module meerdere keren geïmplementeerd.

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

Matrixelementen

In het volgende voorbeeld wordt één opslagaccount gemaakt voor elke naam die in de storageNames parameter is opgegeven. Houd er rekening mee dat de naameigenschap voor elk resource-exemplaar uniek moet zijn.

param location string = resourceGroup().location
param storageNames array = [
  'contoso'
  'fabrikam'
  'coho'
]

resource storageAcct 'Microsoft.Storage/storageAccounts@2022-09-01' = [for name in storageNames: {
  name: '${name}${uniqueString(resourceGroup().id)}'
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'Storage'
}]

In het volgende voorbeeld wordt een matrix herhaald om een eigenschap te definiëren. Er worden twee subnetten binnen een virtueel netwerk gemaakt. Houd er rekening mee dat de subnetnamen uniek moeten zijn.

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@2020-07-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
      }
    }]
  }
}

Matrix en index

In het volgende voorbeeld worden zowel het matrixelement als de indexwaarde gebruikt bij het definiëren van het opslagaccount.

param storageAccountNamePrefix string

var storageConfigurations = [
  {
    suffix: 'local'
    sku: 'Standard_LRS'
  }
  {
    suffix: 'geo'
    sku: 'Standard_GRS'
  }
]

resource storageAccountResources 'Microsoft.Storage/storageAccounts@2022-09-01' = [for (config, i) in storageConfigurations: {
  name: '${storageAccountNamePrefix}${config.suffix}${i}'
  location: resourceGroup().location
  sku: {
    name: config.sku
  }
  kind: 'StorageV2'
}]

In het volgende voorbeeld worden zowel de elementen van een matrix als een index gebruikt om informatie over de nieuwe resources uit te voeren.

param location string = resourceGroup().location
param orgNames array = [
  'Contoso'
  'Fabrikam'
  'Coho'
]

resource nsg 'Microsoft.Network/networkSecurityGroups@2020-06-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
}]

Woordenboekobject

Als u elementen in een woordenlijstobject wilt herhalen, gebruikt u de functie Items, waarmee het object wordt geconverteerd naar een matrix. Gebruik de value eigenschap om eigenschappen op te halen voor de objecten. Houd er rekening mee dat de nsg-resourcenamen uniek moeten zijn.

param nsgValues object = {
  nsg1: {
    name: 'nsg-westus1'
    location: 'westus'
  }
  nsg2: {
    name: 'nsg-east1'
    location: 'eastus'
  }
}

resource nsg 'Microsoft.Network/networkSecurityGroups@2020-06-01' = [for nsg in items(nsgValues): {
  name: nsg.value.name
  location: nsg.value.location
}]

Lus met voorwaarde

Voor resources en modules kunt u een if expressie met de lussyntaxis toevoegen om de verzameling voorwaardelijk te implementeren.

In het volgende voorbeeld ziet u een lus in combinatie met een voorwaarde-instructie. In dit voorbeeld wordt één voorwaarde toegepast op alle exemplaren van de module.

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

In het volgende voorbeeld ziet u hoe u een voorwaarde toepast die specifiek is voor het huidige element in de matrix.

resource parentResources 'Microsoft.Example/examples@2020-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
    }]
  }
}]

Implementeren in batches

Standaard worden Azure-resources parallel geïmplementeerd. Wanneer u een lus gebruikt om meerdere exemplaren van een resourcetype te maken, worden deze exemplaren allemaal tegelijkertijd geïmplementeerd. De volgorde waarin ze worden gemaakt, wordt niet gegarandeerd. Er is geen limiet voor het aantal resources dat parallel is geïmplementeerd, behalve de totale limiet van 800 resources in het Bicep-bestand.

Mogelijk wilt u niet alle exemplaren van een resourcetype tegelijk bijwerken. Als u bijvoorbeeld een productieomgeving bijwerkt, wilt u de updates misschien s stagneren, zodat slechts een bepaald aantal tegelijk wordt bijgewerkt. U kunt opgeven dat een subset van de exemplaren tegelijk worden gebatcheerd en geïmplementeerd. De andere exemplaren wachten tot die batch is voltooid.

Als u exemplaren van een resource serieel wilt implementeren, voegt u de batchSize-decorator toe. Stel de waarde ervan in op het aantal exemplaren dat gelijktijdig moet worden geïmplementeerd. Er wordt een afhankelijkheid gemaakt op eerdere exemplaren in de lus, zodat er pas één batch wordt gestart als de vorige batch is voltooid.

param location string = resourceGroup().location

@batchSize(2)
resource storageAcct 'Microsoft.Storage/storageAccounts@2022-09-01' = [for i in range(0, 4): {
  name: '${i}storage${uniqueString(resourceGroup().id)}'
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'Storage'
}]

Voor sequentiële implementatie stelt u de batchgrootte in op 1.

De batchSize decorator bevindt zich in de sys-naamruimte. Als u deze decorator wilt onderscheiden van een ander item met dezelfde naam, moet u de decorator vooraf laten gaan door sys: @sys.batchSize(2)

Iteratie voor een onderliggende resource

U kunt geen lus gebruiken voor een geneste onderliggende resource. Als u meer dan één exemplaar van een onderliggende resource wilt maken, wijzigt u de onderliggende resource in een resource op het hoogste niveau.

Stel dat u doorgaans een bestandsservice en bestandsshare definieert als geneste resources voor een opslagaccount.

resource stg 'Microsoft.Storage/storageAccounts@2022-09-01' = {
  name: 'examplestorage'
  location: resourceGroup().location
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
  resource service 'fileServices' = {
    name: 'default'
    resource share 'shares' = {
      name: 'exampleshare'
    }
  }
}

Als u meer dan één bestandsshare wilt maken, verplaatst u deze buiten het opslagaccount. U definieert de relatie met de bovenliggende resource via de parent eigenschap.

In het volgende voorbeeld ziet u hoe u een opslagaccount, bestandsservice en meer dan één bestandsshare maakt:

resource stg 'Microsoft.Storage/storageAccounts@2022-09-01' = {
  name: 'examplestorage'
  location: resourceGroup().location
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
}

resource service 'Microsoft.Storage/storageAccounts/fileServices@2021-06-01' = {
  name: 'default'
  parent: stg
}

resource share 'Microsoft.Storage/storageAccounts/fileServices/shares@2021-06-01' = [for i in range(0, 3): {
  name: 'exampleshare${i}'
  parent: service
}]

Referentieresource-/moduleverzamelingen

De functie ARM-sjabloon references retourneert een matrix met objecten die de runtimestatussen van een resourceverzameling vertegenwoordigen. In Bicep is er geen expliciete verwijzingsfunctie. In plaats daarvan wordt het symbolische verzamelingsgebruik rechtstreeks toegepast en tijdens het genereren van code vertaalt Bicep deze naar een ARM-sjabloon die gebruikmaakt van de functie ARM-sjabloonverwijzingen. Voor de vertaalfunctie waarmee symbolische verzamelingen worden omgezet in ARM-sjablonen met behulp van de functie Verwijzingen, is het nodig om Bicep CLI versie 0.20.X of hoger te hebben. Daarnaast moet in het bicepconfig.json bestand de symbolicNameCodegen instelling worden weergegeven en ingesteld op true.

De uitvoer van de twee voorbeelden in de index Integer kan worden geschreven als:

param location string = resourceGroup().location
param storageCount int = 2

resource storageAcct 'Microsoft.Storage/storageAccounts@2022-09-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)

Dit Bicep-bestand wordt omgezet in de volgende ARM JSON-sjabloon die gebruikmaakt van de references functie:

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

Opmerking in de voorgaande ARM JSON-sjabloon languageVersion moet worden ingesteld op 1.10-experimentalen het resource-element is een object in plaats van een matrix.

Volgende stappen