التكرار الحلقي في Bicep

توضح هذه المقالة كيفية استخدامforبناء الجملة للتكرار عبر العناصر الموجودة في مجموعة. يتم دعم هذه الوظيفة بدءاً من الإصدار 0.3.1 فصاعداً. يمكنك استخدام الحلقات لتحديد نسخ متعددة من مورد أو وحدة نمطية أو متغير أو خاصية أو إخراج. استخدم الحلقات لتجنب تكرار بناء الجملة في ملف Bicep الخاص بك ولضبط عدد النسخ للإنشاء أثناء التوزيع بشكل حيوي. للتنقل خلال التشغيل السريع، راجع Quickstart: إنشاء مثيلات متعددة.

لاستخدام التكرارات الحلقية لإنشاء موارد أو وحدات نمطية متعددة، يجب أن يكون لكل مثيل قيمة فريدة لخاصية الاسم. يمكنك استخدام قيمة الفهرس أو القيم الفريدة في الصفائف أو المجموعات لإنشاء الأسماء.

موارد التدريب

إذا كنت تفضل التعرف على التكرارات الحلقية من خلال إرشادات خطوة بخطوة، فراجع إنشاء نماذج مرنة لـ Bicep باستخدام الشروط والتكرارات الحلقية.

بناء جملة حلقي

يمكن إعلان الحلقات بواسطة:

  • استخدام فهرس عدد صحيح. يعمل هذا الخيار عندما يكون السيناريو الخاص بك هو: "أريد إنشاء العديد من الأمثلة." تنشئ دالة النطاق range function صفيفاً من الأعداد الصحيحة تبدأ من فهرس البداية وتحتوي على عدد العناصر المحددة. من خلال الحلقة، يمكنك استخدام فهرس عدد صحيح لتعديل القيم. للمزيد من المعلومات، يرجى مراجعةفهرس التكرار الحلقي.

    [for <index> in range(<startIndex>, <numberOfElements>): {
      ...
    }]
    
  • استخدامالعناصر في صفيف. يعمل هذا الخيار عندما يكون السيناريو الخاص بك هو: "أريد إنشاء مثيل لكل عنصر في الصفيف." داخل الحلقة، يمكنك استخدام قيمة عنصر الصفيف الحالي لتعديل القيم. للمزيد من المعلومات، يرجى مراجعةعناصر الصفيف.

    [for <item> in <collection>: {
      ...
    }]
    
  • استخدامعناصر في عنصر قاموس. يعمل هذا الخيار عندما يكون السيناريو الخاص بك هو: "أريد إنشاء مثيل لكل عنصر في كائن." تحول دالة العناصر الكائن إلى صفيف. من خلال الحلقة، يمكنك استخدام خصائص من العنصر لإنشاء قيم. للمزيد من المعلومات، يرجى مراجعةعنصر القاموس.

    [for <item> in items(<object>): {
      ...
    }]
    
  • استخدامفهرس عدد صحيح والعناصر في صفيف. يعمل هذا الخيار عندما يكون السيناريو الخاص بك هو: "أريد إنشاء مثيل لكل عنصر في صفيف، لكنني أيضاً بحاجة إلى الفهرس الحالي لإنشاء قيمة أخرى." لمزيد من المعلومات، راجع حلقة الصفيف والفهرس.

    [for (<item>, <index>) in <collection>: {
      ...
    }]
    
  • إضافةتوزيع شرطي. يعمل هذا الخيار عندما يكون السيناريو الخاص بك هو: "أريد إنشاء مثيلات متعددة، ولكن لكل حالة أريد نشرها فقط عندما يكون الشرط صحيحاً." لمزيد من المعلومات، راجع التكرار الحلقي مع الشرط.

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

حدود التكرار الحلقي

يتضمن استخدام الحلقات في Bicep هذه القيود:

  • تعمل حلقات Bicep فقط مع القيم التي يمكن تحديدها في بداية النشر.
  • لا يمكن أن تكون التكرارات الحلقية رقمًا سالبًا أو تتجاوز 800 تكرار.
  • لا يمكن تكرار مورد مع موارد التابعة المتداخلة. قم بتغيير "الموارد التابعة" إلى موارد المستوى الأعلى. راجع التكرار لمورد فرعي .
  • للتكرار الحلقي على مستويات متعددة من الخصائص، استخدم دالة خريطة lambda.

فهرس العدد الصحيح

للحصول على مثال بسيط لاستخدام فهرس، أنشئ"متغير"يحتوي على صفيف من السلاسل.

param itemCount int = 5

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

output arrayResult array = stringArray

يعيد الإخراج صفيف بالقيم التالية:

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

يُنشئ المثال التالي عدد حسابات التخزين المحددة فيstorageCountالمعلمة. يقوم بإعادة ثلاث خصائص لكل حساب تخزين.

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

لاحظ استخدام الفهرسiفي إنشاء اسم مورد حساب التخزين.

يوزع المثال التالي وحدة نمطية عدة مرات.

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

عناصر صفيف

يُنشئ المثال التالي حساب تخزين واحد لكل اسم متوفر فيstorageNamesالمعلمة. لاحظ أن خاصية الاسم لكل مثيل مورد يجب أن تكون فريدة.

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

يقوم المثال التالي بالتكرار عبر صفيف لتحديد خاصية. يقوم بإنشاء شبكتين فرعيتين داخل الشبكة الظاهرية. لاحظ أن أسماء الشبكة الفرعية يجب أن تكون فريدة.

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

الصفيف والفهرس

يستخدم المثال التالي كلا من عنصر الصفيف وقيمة الفهرس عند تحديد حساب التخزين.

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

يستخدم المثال التالي كلا من عناصر الصفيف وفهرس لإخراج معلومات حول الموارد الجديدة.

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

عنصر القاموس

للتكرار عبر العناصر الموجودة في عنصر قاموس، استخدم"وظيفة العناصر"، التي تحول العنصر إلى صفيف. استخدمvalue"الخاصية" للحصول على خصائص العناصر. لاحظ أن أسماء موارد nsg يجب أن تكون فريدة.

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

تكرار حلقي مع شرط

للمواردوالوحدات النمطية، يمكنك إضافةifتعبير مع بناء جملة الحلقة لتوزيع المجموعة بشكل مشروط.

يوضح المثال التالي حلقة مقترنة بعبارة شرط. في هذا المثال، يتم تطبيق شرط واحد على كل مثيلات الوحدة النمطية.

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

يوضح المثال التالي طريقة تطبيق شرط خاص بالعنصر الحالي في الصفيف.

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

انشر على دفعات

يتم، بصفة افتراضية توزيع موارد Azure بالتوازي. يتم توزيع كافة هذه المثيلات في نفس الوقت، عند استخدام حلقة لإنشاء مثيلات متعددة من نوع مورد. الترتيب الذي يتم إنشاؤها به غير مضمون. لا يوجد حد لعدد الموارد الموزعة بالتوازي، بخلاف الحد الإجمالي البالغ 800 مورد في ملف Bicep.

قد لا ترغب في تحديث جميع مثيلات نوع المورد في نفس الوقت. على سبيل المثال، عند تحديث بيئة التشغيل، قد تحتاج إلى تنظيم التحديثات بحيث يتم تحديث عدد معين فقط في المرة الواحدة فقط. يمكنك تحديد تجميع مجموعة فرعية من المثيلات معًا ونشرها في نفس الوقت. تنتظر المثيلات الأخرى حتى تكتمل تلك الدفعة.

لتوزيع مثيلات مورد بشكل تسلسلي، أضف"مصمم batchSize". عيّن قيمته على عدد المثيلات التي سيتم نشرها بشكل متزامن. يتم إنشاء تبعية على مثيلات سابقة في الحلقة؛ لذلك لا يبدأ تجميع دفعة حتى تكتمل الدفعة السابقة.

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

للتوزيع المتسلسل، قم بتعيين "حجم المجموعة إلى 1".

batchSizeالمصمم فيمساحة الاسم sys. إذا كنت بحاجة إلى تفريق هذا المصمم من عنصر آخر يحمل نفس الاسم، فاكتب في مقدمة المصمم sys: @sys.batchSize(2)

تكرار لمورد تابع

لا يمكنك استخدام حلقة لمورد فرعي متداخل. قم بتغيير المورد التابع إلى مورد المستوى الأعلى، ليتم إنشاء أكثر من مثيل واحد من مورد تابع.

على سبيل المثال، افترض أنك تعرف عادةً خدمة الملفات ومشاركة الملفات كموارد متداخلة لحساب التخزين.

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

لإنشاء أكثر من مشاركة ملف، انقلها خارج حساب التخزين. تقوم بتعريف العلاقة مع المورد الرئيسي من خلال خاصية parent.

يوضح المثال التالي كيفية إنشاء حساب تخزين وخدمة الملفات وأكثر من مشاركة ملف:

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

مجموعات الموارد/الوحدة النمطية المرجعية

ترجع دالة قالب references ARM صفيفا من الكائنات التي تمثل حالات وقت تشغيل مجموعة الموارد. في Bicep، لا توجد دالة مراجع صريحة. بدلا من ذلك، يتم استخدام استخدام المجموعة الرمزية مباشرة، وأثناء إنشاء التعليمات البرمجية، يترجمه Bicep إلى قالب ARM الذي يستخدم دالة مراجع قالب ARM. بالنسبة لميزة الترجمة التي تحول المجموعات الرمزية إلى قوالب ARM باستخدام دالة المراجع، من الضروري أن يكون Bicep CLI الإصدار 0.20.X أو أعلى. بالإضافة إلى ذلك، في bicepconfig.json الملف، symbolicNameCodegen يجب تقديم الإعداد وتعيينه إلى true.

يمكن كتابة مخرجات العينتين في فهرس عدد صحيح على النحو التالي:

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)

يتم تحويل ملف Bicep هذا إلى قالب ARM JSON التالي الذي يستخدم الدالة 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": "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))]"
    }
  }
}

لاحظ في قالب ARM JSON السابق، languageVersion يجب تعيين إلى 1.10-experimental، وعنصر المورد هو كائن بدلا من صفيف.

الخطوات التالية

  • للتعرف على كيفية إنشاء ملفات Bicep، راجع الملف.