Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym artykule pokazano, jak używać składni for
do przechodzenia przez elementy w kolekcji. Ta funkcja jest obsługiwana od wersji 0.3.1 do nowszej. Pętle umożliwiają definiowanie wielu kopii zasobu, modułu, zmiennej, właściwości lub danych wyjściowych. Użyj pętli, aby uniknąć powtarzania składni w pliku Bicep i dynamicznie ustawiać liczbę kopii do utworzenia podczas wdrażania. Zobacz Szybki start: tworzenie wielu wystąpień zasobów w środowisku Bicep, aby dowiedzieć się, jak używać różnych for
składni do tworzenia wielu wystąpień zasobów w Bicep.
Aby używać pętli do tworzenia wielu zasobów lub modułów, każde wystąpienie musi mieć unikatową wartość dla name
właściwości. Aby utworzyć nazwy, możesz użyć wartości indeksu lub unikatowych wartości w tablicach lub kolekcjach.
Zasoby szkoleniowe
Aby uzyskać szczegółowe wskazówki dotyczące pętli, zobacz moduł Tworzenie elastycznych plików Bicep przy użyciu warunków i pętli w Microsoft Learn.
Składnia pętli
Deklarowanie pętli może odbywać się poprzez:
Za pomocą indeksu liczb całkowitych. Ta opcja działa, gdy twój scenariusz to: "Chcę utworzyć tyle wystąpień". Funkcja range tworzy tablicę liczb całkowitych, rozpoczynającą się od indeksu początkowego i zawierającą określoną liczbę elementów. W pętli można użyć indeksu liczby całkowitej, aby zmodyfikować wartości. Aby uzyskać więcej informacji, zobacz Indeks liczb całkowitych.
[for <index> in range(<startIndex>, <numberOfElements>): { ... }]
Używanie elementów w tablicy: ta opcja działa, gdy scenariusz to "Chcę utworzyć wystąpienie dla każdego elementu w tablicy". W pętli można użyć wartości bieżącego elementu tablicy, aby zmodyfikować wartości. Aby uzyskać więcej informacji, zobacz Elementy tablicy.
[for <item> in <collection>: { ... }]
Używanie elementów w obiekcie słownika: ta opcja działa, gdy scenariusz to "Chcę utworzyć wystąpienie dla każdego elementu w obiekcie". Funkcja items konwertuje obiekt na tablicę. W ramach pętli można użyć właściwości z obiektu do utworzenia wartości. Aby uzyskać więcej informacji, zobacz obiekt słownika.
[for <item> in items(<object>): { ... }]
Użycie indeksu całkowitego i elementów w tablicy: ta opcja działa, gdy scenariusz to "Chcę utworzyć wystąpienie dla każdego elementu w tablicy, ale potrzebuję również bieżącego indeksu, aby utworzyć inną wartość". Aby uzyskać więcej informacji, zobacz Tablica pętli i indeks.
[for (<item>, <index>) in <collection>: { ... }]
Dodawanie wdrożenia warunkowego: Ta opcja działa, gdy scenariusz to "Chcę utworzyć wiele wystąpień, ale chcę wdrożyć każde wystąpienie tylko wtedy, gdy warunek jest spełniony". Aby uzyskać więcej informacji, zobacz Pętla z warunkiem.
[for <item> in <collection>: if(<condition>) { ... }]
Limity pętli
Używanie pętli w Bicep ma następujące ograniczenia:
- Pętle Bicep działają wyłącznie z wartościami, które da się określić na początku wdrożenia.
- Iteracje pętli nie mogą być liczbą ujemną ani przekraczać 800 iteracji.
- Ponieważ zasób nie może działać w pętli z zagnieżdżonymi zasobami podrzędnymi, zmień zasoby podrzędne na zasoby najwyższego poziomu. Aby uzyskać więcej informacji, zobacz Iteracja dla zasobu potomnego.
- Aby przeprowadzić pętlę na wielu poziomach właściwości, użyj funkcji lambda
map
.
Indeks liczby całkowitej
Aby uzyskać prosty przykład użycia indeksu, utwórz zmienną zawierającą tablicę ciągów:
param itemCount int = 5
var stringArray = [for i in range(0, itemCount): 'item${(i + 1)}']
output arrayResult array = stringArray
Dane wyjściowe zwracają tablicę z następującymi wartościami:
[
"item1",
"item2",
"item3",
"item4",
"item5"
]
W następnym przykładzie pokazano utworzenie liczby kont magazynowych określonych w parametrze storageCount
. Zwraca trzy właściwości dla każdego konta pamięci masowej:
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
}]
Zwróć uwagę, że indeks i
jest używany przy tworzeniu nazwy zasobu konta pamięci masowej.
W następnym przykładzie jest wdrażany moduł wiele razy:
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
}]
Elementy tablicy
Poniższy przykład tworzy jedno konto magazynowe dla każdej nazwy podanej w parametrze storageNames
. Pamiętaj, że atrybut name dla każdego wystąpienia zasobu musi być unikatowy.
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'
}]
W następnym przykładzie iteruje po tablicy, aby zdefiniować właściwość. Tworzy dwie podsieci w sieci wirtualnej. Pamiętaj, że nazwy podsieci muszą być unikatowe:
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
}
}]
}
}
Tablica i indeks
W następującym przykładzie użyto zarówno elementu tablicy, jak i wartości indeksu podczas definiowania konta pamięci masowej.
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'
}]
W następnym przykładzie użyto zarówno elementów tablicy, jak i indeksu, aby uzyskać informacje o nowych zasobach:
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
}]
Obiekt słownika
Aby iterować elementy w obiekcie słownika, użyj items
funkcji, która konwertuje obiekt na tablicę. Użyj właściwości value
, aby uzyskać właściwości na obiektach. Pamiętaj, że nazwy zasobów sieciowej grupy zabezpieczeń muszą być unikatowe.
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
}]
Pętla z warunkiem
W przypadku zasobów i modułów można dodać if
wyrażenie ze składnią pętli w celu warunkowego wdrożenia kolekcji.
W poniższym przykładzie przedstawiono pętlę połączoną z instrukcją warunkową. W tym przykładzie pojedynczy warunek jest stosowany do wszystkich wystąpień modułu:
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
}
}]
W następnym przykładzie pokazano, jak zastosować warunek specyficzny dla bieżącego elementu w tablicy:
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
}]
}
}]
Wdrażanie w partiach
Zasoby platformy Azure są wdrażane równolegle domyślnie. Gdy używasz pętli do tworzenia wielu wystąpień typu zasobu, wszystkie te wystąpienia są wdrażane w tym samym czasie. Kolejność ich tworzenia nie jest gwarantowana. Nie ma limitu liczby zasobów wdrażanych równolegle, oprócz łącznego limitu 800 zasobów w pliku Bicep.
Możesz nie chcieć zaktualizować wszystkich wystąpień typu zasobu w tym samym czasie. Na przykład podczas aktualizowania środowiska produkcyjnego, możesz chcieć stopniowo aktualizować tylko określoną liczbę zasobów jednocześnie. Można określić podzbiór wystąpień, które mają być grupowane i wdrażane jednocześnie. Inne instancje czekają na ukończenie tej partii.
Aby szeregowo wdrożyć instancje zasobu, dodaj batchSize
dekorator. Ustaw jej wartość na liczbę wystąpień, które mają być wdrażane współbieżnie. Zależność jest tworzona podczas wcześniejszych wystąpień w pętli, więc nie uruchamia jednej partii, dopóki poprzednia partia nie zostanie ukończona.
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'
}]
W przypadku wdrożenia sekwencyjnego ustaw rozmiar partii na 1.
Dekorator batchSize
znajduje się w przestrzeni nazw systemu. Jeśli chcesz odróżnić ten dekorator od innego elementu o tej samej nazwie, poprzedź dekorator za pomocą sys: @sys.batchSize(2)
Iteracja zasobu podrzędnego
Aby utworzyć więcej niż jedno wystąpienie zasobu podrzędnego, oba następujące pliki Bicep obsługują to zadanie:
Zagnieżdżone zasoby podrzędne
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}'
}]
}
}
Zasoby podrzędne najwyższego poziomu
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
}]
Referencyjne kolekcje zasobów/modułów
Funkcja szablonu usługi Azure Resource Manager (szablon ARM) references
zwraca tablicę obiektów reprezentujących stany wykonawcze zestawu zasobów. Ponieważ w Bicep nie istnieje jawna funkcja references
i użycie kolekcji symbolicznej jest stosowane bezpośrednio, Bicep tłumaczy użycie symboliczne na szablon ARM, który korzysta z funkcji references
szablonu ARM podczas generowania kodu. Aby funkcjonalność tłumaczenia mogła używać references
do przekształcania kolekcji symbolicznych w szablony ARM, konieczne jest posiadanie wersji interfejsu wiersza polecenia Bicep 0.20.X lub nowszej. Ponadto w pliku bicepconfig.json należy przedstawić i zastosować ustawienie symbolicNameCodegen
na wartość true
.
Dane wyjściowe dwóch próbek w indeksu liczby całkowitej można zapisać je jako:
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)
Ten plik Bicep jest transpilowany do następującego szablonu JSON ARM, który używa funkcji 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))]"
}
}
}
Zwróć uwagę, że w poprzednim szablonie ARM JSON languageVersion
musi być ustawione na 1.10-experimental
, a element zasobu jest obiektem, a nie tablicą.
Następne kroki
Aby dowiedzieć się, jak tworzyć pliki Bicep, zobacz Bicep file structure and syntax (Struktura i składnia plików Bicep).