Perulangan iteratif di Bicep

Artikel ini menunjukkan cara menggunakan sintaks for untuk mengulangi item dalam koleksi. Fungsi ini didukung mulai dari v0.3.1 dan seterusnya. Anda dapat menggunakan perulangan untuk menentukan banyak salinan sumber daya, modul, variabel, properti, atau output. Gunakan perulangan untuk menghindari pengulangan sintaks dalam file Bicep Anda dan untuk secara dinamis mengatur jumlah salinan yang akan dibuat selama penyebaran. Untuk memulai dengan cepat, lihat Mulai cepat: Membuat beberapa contoh.

Untuk menggunakan perulangan untuk membuat beberapa sumber daya atau modul, setiap instans harus memiliki nilai unik untuk properti nama. Anda dapat menggunakan nilai indeks atau nilai unik dalam array atau koleksi untuk membuat nama.

Sumber daya pelatihan

Jika Anda ingin mempelajari perulangan melalui panduan langkah demi langkah, lihat Membangun template Bicep yang fleksibel dengan menggunakan kondisi dan perulangan.

Sintaks perulangan

Perulangan dapat dideklarasikan dengan:

  • Menggunakan indeks bilangan bulat. Opsi ini bekerja saat skenario Anda adalah: "Saya ingin membuat banyak hal ini." Fungsi range membuat array bilangan bulat yang dimulai di indeks awal dan berisi jumlah elemen yang ditentukan. Dalam perulangan, Anda dapat menggunakan indeks bilangan bulat untuk mengubah nilai. Untuk informasi selengkapnya, lihat Indeks bilangan bulat.

    [for <index> in range(<startIndex>, <numberOfElements>): {
      ...
    }]
    
  • Menggunakan item dalam array. Opsi ini bekerja saat skenario Anda adalah: "Saya ingin membuat instans untuk setiap elemen dalam array." Di dalam perulangan, Anda dapat menggunakan nilai elemen array saat ini untuk mengubah nilai. Untuk informasi selengkapnya, lihat Elemen array.

    [for <item> in <collection>: {
      ...
    }]
    
  • Menggunakan item dalam objek kamus. Opsi ini berfungsi ketika skenario Anda adalah: "Saya ingin membuat instans untuk setiap item dalam objek." Fungsi item akan mengonversi objek menjadi array. Dalam perulangan, Anda dapat menggunakan properti dari objek untuk membuat nilai. Untuk informasi selengkapnya, lihat Objek kamus.

    [for <item> in items(<object>): {
      ...
    }]
    
  • Menggunakan indeks bilangan bulat dan item dalam array. Opsi ini berfungsi ketika skenario Anda adalah: "Saya ingin membuat instans untuk setiap elemen dalam array, tetapi saya juga memerlukan indeks saat ini untuk membuat nilai lain." Untuk informasi lebih lanjut, lihat Array dan indeks perulangan.

    [for (<item>, <index>) in <collection>: {
      ...
    }]
    
  • Menambahkan penyebaran kondisional. Opsi ini berfungsi jika skenario Anda adalah: "Saya ingin membuat beberapa instans, tetapi untuk setiap instans saya hanya ingin menyebarkan jika kondisinya benar." Untuk informasi selengkapnya, lihat Perulangan dengan kondisi.

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

Batas perulangan

Menggunakan perulangan di Bicep memiliki keterbatasan ini:

  • Perulangan Bicep hanya berfungsi dengan nilai yang dapat ditentukan pada awal penyebaran.
  • Iterasi perulangan file Bicep tidak boleh berupa angka negatif atau melebihi 800 perulangan.
  • Tidak dapat memutar sumber daya dengan sumber daya anak bersarang. Ubah sumber daya turunan menjadi sumber daya tingkat atas. Lihat Iterasi untuk sumber daya anak.
  • Untuk mengulang beberapa tingkat properti, gunakan fungsi peta lambda.

indeks bilangan bulat

Untuk contoh sederhana penggunaan indeks, buat variabel yang berisi array string.

param itemCount int = 5

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

output arrayResult array = stringArray

Output menghasilkan array dengan nilai-nilai berikut:

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

Contoh berikutnya membuat jumlah akun penyimpanan yang ditentukan dalam parameter storageCount. Hal ini menampilkan tiga properti untuk setiap akun penyimpanan.

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

Perhatikan bahwa indeks i digunakan dalam membuat nama sumber daya akun penyimpanan.

Contoh berikutnya menyebarkan modul beberapa kali.

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

Elemen array

Contoh berikut membuat satu akun penyimpanan untuk setiap nama yang diberikan dalam parameter storageNames. Perhatikan properti nama untuk setiap instans sumber daya harus unik.

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

Contoh berikutnya mengulangi array untuk menentukan properti. Hal ini membuat dua subnet dalam jaringan virtual. Perhatikan bahwa nama subnet harus unik.

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

Array dan indeks

Contoh berikut menggunakan elemen array dan nilai indeks saat menentukan akun penyimpanan.

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

Contoh berikutnya menggunakan elemen array dan indeks untuk menampilkan informasi tentang sumber daya baru.

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

Objek kamus

Untuk mengulangi elemen dalam objek kamus, gunakan fungsi item, yang mengonversi objek menjadi array. Gunakan properti value untuk mendapatkan properti pada objek. Perhatikan bahwa nama sumber daya nsg harus unik.

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

Perulangan dengan kondisi

Untuk sumber daya dan modul, Anda dapat menambahkan ekspresi if dengan sintaks perulangan guna menyebarkan koleksi secara kondisional.

Contoh berikut menunjukkan perulangan yang dikombinasikan dengan pernyataan kondisi. Dalam contoh ini, satu kondisi diterapkan ke semua instans modul.

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

Contoh berikutnya menunjukkan cara menerapkan kondisi yang khusus untuk elemen saat ini dalam array.

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

Menyebarkan dalam batch

Secara default, sumber daya Azure disebarkan secara paralel. Saat Anda menggunakan perulangan untuk membuat beberapa instans dari jenis sumber daya, semua instans tersebut disebarkan pada waktu yang sama. Urutan pembuatannya tidak dijamin. Tidak ada batasan jumlah sumber daya yang digunakan secara paralel, selain batas total 800 sumber daya dalam file Bicep.

Anda mungkin tidak ingin memperbarui semua instans dari jenis sumber daya secara bersamaan. Misalnya, saat memperbarui lingkungan produksi, Anda mungkin ingin mengejutkan pembaruan sehingga hanya angka tertentu yang diperbarui pada satu waktu. Anda dapat menentukan bahwa subset dari instans dikumpulkan bersama dan digunakan pada saat yang sama. Contoh lain menunggu batch itu selesai.

Untuk menyebarkan contoh sumber daya secara serial, tambahkan dekorator batchSize. Tetapkan nilainya ke jumlah instance yang akan di-deploy secara bersamaan. Dependensi dibuat pada instans sebelumnya dalam perulangan, sehingga tidak memulai satu batch hingga batch sebelumnya selesai.

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

Untuk penyebaran berurutan, atur ukuran batch ke 1.

Dekorator batchSize berada dalam namespace layanan sys. Jika Anda perlu membedakan dekorator ini dari item lainnya dengan nama yang sama, awali dekorator dengan sys: @sys.batchSize(2)

Perulangan untuk sumber daya anak

Anda tidak dapat menggunakan perulangan untuk sumber daya turunan berlapis. Untuk membuat lebih dari satu instans sumber daya anak, ubah sumber daya anak menjadi sumber daya tingkat atas.

Misalnya, misalkan Anda biasanya mendefinisikan layanan file dan berbagi file sebagai sumber daya berlapis untuk akun penyimpanan.

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

Untuk membuat lebih dari satu berbagi file, pindahkan ke luar akun penyimpanan. Anda menentukan hubungan dengan sumber daya induk melalui properti parent.

Contoh berikut menunjukkan cara membuat akun penyimpanan, layanan file, dan lebih dari satu berbagi file:

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

Mereferensikan kumpulan sumber daya/modul

Fungsi templat references ARM mengembalikan array objek yang mewakili status runtime kumpulan sumber daya. Di Bicep, tidak ada fungsi referensi eksplisit. Sebaliknya, penggunaan koleksi simbolis digunakan secara langsung, dan selama pembuatan kode, Bicep menerjemahkannya ke templat ARM yang menggunakan fungsi referensi templat ARM. Untuk fitur terjemahan yang mengubah koleksi simbolis menjadi templat ARM menggunakan fungsi referensi, perlu memiliki Bicep CLI versi 0.20.X atau lebih tinggi. Selain itu, dalam bicepconfig.json file, symbolicNameCodegen pengaturan harus disajikan dan diatur ke true.

Output dari dua sampel dalam indeks Bilangan Bulat dapat ditulis sebagai:

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)

File Bicep ini ditranspilasi ke dalam templat ARM JSON berikut yang menggunakan references fungsi :

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

Catatan dalam templat ARM JSON sebelumnya, languageVersion harus diatur ke 1.10-experimental, dan elemen sumber daya adalah objek alih-alih array.

Langkah berikutnya

  • Untuk mempelajari tentang membuat file Bicep, lihat file.