Iterativní smyčky v Bicep

V tomto článku se dozvíte, jak pomocí for syntaxe iterovat položky v kolekci. Tato funkce se podporuje od verze 0.3.1 dále. Pomocí smyček můžete definovat více kopií prostředku, modulu, proměnné, vlastnosti nebo výstupu. Pomocí smyček se vyhnete opakování syntaxe v souboru Bicep a dynamicky nastavíte počet kopií, které se mají během nasazení vytvořit. Pokud chcete projít rychlý start, přečtěte si článek Rychlý start: Vytvoření více instancí.

Pokud chcete k vytvoření více prostředků nebo modulů použít smyčky, musí mít každá instance jedinečnou hodnotu vlastnosti name. Názvy můžete vytvořit pomocí hodnoty indexu nebo jedinečných hodnot v polích nebo kolekcích.

Školící materiály

Pokud byste se raději dozvěděli o smyčkách podrobných pokynů, přečtěte si téma Vytváření flexibilních šablon Bicep pomocí podmínek a smyček.

Syntaxe smyčky

Smyčky lze deklarovat pomocí:

  • Použití celočíselného indexu Tato možnost funguje, pokud je váš scénář: "Chci vytvořit tento počet instancí". Funkce rozsahu vytvoří pole celých čísel, které začínají na počátečním indexu a obsahují počet zadaných prvků. Ve smyčce můžete k úpravě hodnot použít celočíselné indexy. Další informace naleznete v tématu Integer index.

    [for <index> in range(<startIndex>, <numberOfElements>): {
      ...
    }]
    
  • Použití položek v poli Tato možnost funguje, pokud je váš scénář: "Chci vytvořit instanci pro každý prvek v poli". Ve smyčce můžete k úpravě hodnot použít hodnotu aktuálního prvku pole. Další informace naleznete v tématu Prvky pole.

    [for <item> in <collection>: {
      ...
    }]
    
  • Použití položek v objektu slovníku Tato možnost funguje, pokud je váš scénář: "Chci vytvořit instanci pro každou položku v objektu". Funkce items převede objekt na pole. Ve smyčce můžete k vytvoření hodnot použít vlastnosti z objektu. Další informace naleznete v tématu Dictionary objekt.

    [for <item> in items(<object>): {
      ...
    }]
    
  • Použití celočíselného indexu a položek v poli Tato možnost funguje, když je váš scénář: "Chci vytvořit instanci pro každý prvek v poli, ale k vytvoření další hodnoty potřebuji také aktuální index." Další informace naleznete v tématu Smyčka pole a index.

    [for (<item>, <index>) in <collection>: {
      ...
    }]
    
  • Přidání podmíněného nasazení Tato možnost funguje, pokud je váš scénář: "Chci vytvořit více instancí, ale pro každou instanci, kterou chci nasadit pouze v případě, že je splněna podmínka". Další informace naleznete v tématu Smyčka s podmínkou.

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

Omezení smyčky

Používání smyček v Bicep má tato omezení:

  • Smyčky Bicep pracují pouze s hodnotami, které je možné určit na začátku nasazení.
  • Iterace smyčky nesmí být záporné číslo nebo nesmí překročit 800 iterací.
  • Prostředek nelze opakovat s vnořenými podřízenými prostředky. Změňte podřízené prostředky na prostředky nejvyšší úrovně. Viz iterace pro podřízený prostředek.
  • Pokud chcete provést smyčku na více úrovních vlastností, použijte funkci mapování lambda.

Celočíselná index

Pro jednoduchý příklad použití indexu vytvořte proměnnou, která obsahuje pole řetězců.

param itemCount int = 5

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

output arrayResult array = stringArray

Výstup vrátí matici s následujícími hodnotami:

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

Další příklad vytvoří počet účtů úložiště zadaných v parametru storageCount . Vrátí tři vlastnosti pro každý účet úložiště.

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

Všimněte si, že se index i používá při vytváření názvu prostředku účtu úložiště.

Další příklad několikrát nasadí modul.

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

Prvky pole

Následující příklad vytvoří jeden účet úložiště pro každý název zadaný v parametru storageNames . Poznamenejte si vlastnost názvu pro každou instanci prostředku musí být jedinečná.

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

Další příklad iteruje přes pole k definování vlastnosti. Vytvoří dvě podsítě ve virtuální síti. Všimněte si, že názvy podsítí musí být jedinečné.

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

Pole a index

V následujícím příkladu se při definování účtu úložiště používá element pole i hodnota indexu.

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

V dalším příkladu se k výstupu informací o nových prostředcích používají prvky pole i index.

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

Objekt slovníku

Chcete-li iterovat prvky v objektu slovníku, použijte funkci items, která převede objekt na pole. value Vlastnost slouží k získání vlastností objektů. Všimněte si, že názvy prostředků NSG musí být jedinečné.

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

Smyčka s podmínkou

Pro prostředky a moduly můžete přidat if výraz se syntaxí smyčky pro podmíněné nasazení kolekce.

Následující příklad ukazuje smyčku v kombinaci s příkazem podmínky. V tomto příkladu se pro všechny instance modulu použije jedna podmínka.

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

Další příklad ukazuje, jak použít podmínku specifickou pro aktuální prvek v poli.

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

Nasazení v dávkách

Ve výchozím nastavení se prostředky Azure nasazují paralelně. Když k vytvoření více instancí typu prostředku použijete smyčku, všechny tyto instance se nasadí současně. Pořadí, ve kterém jsou vytvořené, není zaručeno. Počet prostředků nasazených paralelně není omezen, kromě celkového limitu 800 prostředků v souboru Bicep.

Možná nebudete chtít aktualizovat všechny instance typu prostředku najednou. Například při aktualizaci produkčního prostředí můžete chtít aktualizace rozmístit tak, aby se aktualizovalo jenom určité číslo najednou. Můžete určit, že podmnožina instancí se dávková společně a současně nasadí. Ostatní instance čekají na dokončení této dávky.

Chcete-li serialně nasadit instance prostředku, přidejte dekorátor batchSize. Nastavte jeho hodnotu na počet instancí, které se mají nasadit souběžně. Závislost se vytvoří na dřívějších instancích ve smyčce, takže nespustí jednu dávku, dokud se předchozí dávka nedokončí.

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

Pro sekvenční nasazení nastavte velikost dávky na 1.

Dekorátor batchSize je v oboru názvů sys. Pokud potřebujete odlišit tento dekorátor od jiné položky se stejným názvem, předkožte dekorátor sys:@sys.batchSize(2)

Iterace pro podřízený prostředek

Smyčku nemůžete použít pro vnořený podřízený prostředek. Pokud chcete vytvořit více než jednu instanci podřízeného prostředku, změňte podřízený prostředek na prostředek nejvyšší úrovně.

Předpokládejme například, že pro účet úložiště obvykle definujete souborovou službu a sdílenou složku jako vnořené prostředky.

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

Pokud chcete vytvořit více než jednu sdílenou složku, přesuňte ji mimo účet úložiště. Vztah s nadřazeným prostředkem definujete prostřednictvím parent vlastnosti.

Následující příklad ukazuje, jak vytvořit účet úložiště, souborovou službu a více než jednu sdílenou složku:

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

Referenční kolekce prostředků nebo modulů

Funkce šablony references ARM vrátí pole objektů představujících stavy modulu runtime kolekce prostředků. V Bicep neexistuje žádná explicitní odkazová funkce. Místo toho se používá symbolické použití kolekce přímo a během generování kódu ji Bicep přeloží na šablonu ARM, která využívá funkci odkazy na šablonu ARM. Pro funkci překladu, která transformuje symbolické kolekce na šablony ARM pomocí funkce reference, je nutné mít Rozhraní příkazového řádku Bicep verze 0.20.X nebo vyšší. Kromě toho bicepconfig.json v souboru symbolicNameCodegen by mělo být nastavení prezentováno a nastaveno na true.

Výstupy dvou ukázek v celočíselném indexu lze zapsat takto:

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)

Tento soubor Bicep se přeloží do následující šablony references JSON ARM, která tuto funkci využívá:

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

Všimněte si, že v předchozí šabloně languageVersion JSON ARM musí být nastavena na 1.10-experimentalhodnotu a prvek prostředku je objekt místo pole.

Další kroky

  • Další informace o vytváření souborů Bicep najdete v souboru.