قم بتطبيق محول خاصية ومجمع في قالب Azure Resource Manager

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

للتغلب على ذلك، يمكنك تنفيذ تحويل خاصية وقالب مجمع يكرر صفيف العنصر الخاص بك ويحوله إلى مخطط JSON للمورد.

هام

يتطلب هذا الأسلوب أن يكون لديك فهم عميق لقوالب ووظائف Azure Resource Manager.

لنلق نظرة على مثال ينفذ مجمع خصائص ومحول لنشر مجموعة أمان شبكة. يوضح الرسم التخطيطي أدناه كيفية ارتباط قوالبنا بالموارد الموجودة في هذه القوالب:

بنية مجمع الخصائص والمحول

يشتمل قالب الاتصال على مصدرين:

  • ارتباط قالب يستدعي قالب المجمع الخاص بنا
  • مورد مجموعة أمان الشبكة المراد نشره

يتضمن قالب المُجمع الخاص بنا مصدرين:

  • مورد ارتساء
  • ارتباط قالب يستدعي قالب التحويل في حلقة نسخ

يتضمن قالب التحويل الخاص بنا موردا واحدا: قالب فارغ مع متغير يحول JSON الخاص بنا source إلى مخطط JSON المتوقع من قبل مورد مجموعة أمان الشبكة في القالب الرئيسي.

عنصر المعلمة

نستخدم كائن المعلمة من استخدام الكائنات كمعلمات في حلقة نسخ في قالب Azure Resource Manager.securityRules يحول قالب التحويل الخاص بنا كل كائن في securityRules الصفيف إلى مخطط JSON المتوقع من قبل مورد مجموعة أمان الشبكة في قالب الاستدعاء الخاص بنا.

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "networkSecurityGroupsSettings": {
            "value": {
                "securityRules": [
                    {
                        "name": "RDPAllow",
                        "description": "allow RDP connections",
                        "direction": "Inbound",
                        "priority": 100,
                        "sourceAddressPrefix": "*",
                        "destinationAddressPrefix": "10.0.0.0/24",
                        "sourcePortRange": "*",
                        "destinationPortRange": "3389",
                        "access": "Allow",
                        "protocol": "Tcp"
                    },
                    {
                        "name": "HTTPAllow",
                        "description": "allow HTTP connections",
                        "direction": "Inbound",
                        "priority": 200,
                        "sourceAddressPrefix": "*",
                        "destinationAddressPrefix": "10.0.1.0/24",
                        "sourcePortRange": "*",
                        "destinationPortRange": "80",
                        "access": "Allow",
                        "protocol": "Tcp"
                    }
                ]
            }
        }
    }
}

لنلقِ نظرة على قالب التحويل أولاً.

قالب التحويل

يتضمن قالب التحويل الخاص بنا معلمتين تم تمريرهما من قالب المجمع:

  • source هو عنصر يتلقى أحد عناصر قيمة الخاصية من صفيف الخاصية. في مثالنا، يتم تمرير كل كائن من securityRules الصفيف واحدا تلو الآخر.
  • state عبارة عن صفيف تتلقى النتائج المتسلسلة لجميع التحويلات السابقة. هذه هي مجموعة JSON المحولة.

تبدو معلماتنا كما يلي:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "source": {
            "type": "object"
        },
        "state": {
            "type": "array",
            "defaultValue": []
        }
    },

يحدد القالب أيضا متغيرا يسمى instance يحول عنصرنا source إلى مخطط JSON المطلوب:

"variables": {
    "instance": [
        {
            "name": "[parameters('source').name]",
            "properties": {
                "description": "[parameters('source').description]",
                "protocol": "[parameters('source').protocol]",
                "sourcePortRange": "[parameters('source').sourcePortRange]",
                "destinationPortRange": "[parameters('source').destinationPortRange]",
                "sourceAddressPrefix": "[parameters('source').sourceAddressPrefix]",
                "destinationAddressPrefix": "[parameters('source').destinationAddressPrefix]",
                "access": "[parameters('source').access]",
                "priority": "[parameters('source').priority]",
                "direction": "[parameters('source').direction]"
            }
        }
    ]
}

وأخيرا، output يقوم القالب الخاص بنا بتسلسل التحويلات المجمعة لمعلمتنا state مع التحويل الحالي الذي يتم تنفيذه بواسطة متغيرنا instance :

"resources": [],
"outputs": {
    "collection": {
        "type": "array",
        "value": "[concat(parameters('state'), variables('instance'))]"
    }
}

بعد ذلك، دعونا نلقي نظرة على قالب المجمع الخاص بنا لمعرفة كيفية تمرير قيم المعلمات الخاصة بنا.

قالب جامع

يشتمل قالب المُجمع الخاص بنا على ثلاث معلمات:

  • source هو صفيف عناصر المعلمات الكاملة. يتم تمريره بواسطة قالب الاستدعاء. له نفس اسم المعلمة source في قالب التحويل الخاص بنا، ولكن هناك اختلاف رئيسي واحد: على الرغم من أنه الصفيف الكامل، فإننا نمرر عنصر صفيف واحد فقط في كل مرة إلى قالب التحويل.
  • transformTemplateUri هو URI الخاص بـ قالب التحويلالخاص بنا. نحن نحددها كمعلمة لإعادة استخدام القالب.
  • state عبارة عن صفيف فارغة في البداية نمررها إلى قالب التحويل. يخزن مجموعة كائنات المعلمات المحولة بعد انتهاء حلقة النسخ.

تبدو معلماتنا كما يلي:

"parameters": {
    "source": {
        "type": "array"
    },
    "transformTemplateUri": {
        "type": "string"
    },
    "state": {
        "type": "array",
        "defaultValue": []
    }
}

بعد ذلك، نحدد متغيراً اسمه count. قيمته هي طول صفيف عنصر المعلمة source :

"variables": {
    "count": "[length(parameters('source'))]"
}

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

الآن دعونا نلقي نظرة على مواردنا. نحدد مصدرين:

  • loop-0 هو المورد الصفري لحلقة النسخ الخاصة بنا.
  • loop- بنتيجة الوظيفة copyIndex(1)يتم الربط لإنشاء اسم فريد مستند إلى التكرار لموردنا، بدءاً من 1.

تبدو مواردنا كما يلي:

"resources": [
    {
        "type": "Microsoft.Resources/deployments",
        "apiVersion": "2015-01-01",
        "name": "loop-0",
        "properties": {
            "mode": "Incremental",
            "parameters": { },
            "template": {
                "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
                "contentVersion": "1.0.0.0",
                "parameters": { },
                "variables": { },
                "resources": [ ],
                "outputs": {
                    "collection": {
                        "type": "array",
                        "value": "[parameters('state')]"
                    }
                }
            }
        }
    },
    {
        "type": "Microsoft.Resources/deployments",
        "apiVersion": "2015-01-01",
        "name": "[concat('loop-', copyindex(1))]",
        "copy": {
            "name": "iterator",
            "count": "[variables('count')]",
            "mode": "serial"
        },
        "dependsOn": [
            "loop-0"
        ],
        "properties": {
            "mode": "Incremental",
            "templateLink": { "uri": "[parameters('transformTemplateUri')]" },
            "parameters": {
                "source": { "value": "[parameters('source')[copyindex()]]" },
                "state": { "value": "[reference(concat('loop-', copyindex())).outputs.collection.value]" }
            }
        }
    }
]

دعونا نلقي نظرة فاحصة على المعلمات التي نمررها إلى قالب التحويل الخاص بنا في القالب المتداخل. تذكر مما سبق أن معلمة source الخاصة بنا تمرر العنصر الحالي في صفيف عنصر المعلمة source. المعلمة state هي المكان الذي تحدث فيه المجموعة، لأنها تأخذ إخراج التكرار السابق لحلقة النسخ الخاصة بنا وتمريرها إلى التكرار الحالي. لاحظ أن الدالة reference() تستخدم الدالة copyIndex() بدون معلمة للإشارة إلى كائن القالب name المرتبط السابق.

أخيراً، يعرض output القالب الخاص بنا output التكرار الأخير لقالب التحويل:

"outputs": {
    "result": {
        "type": "array",
        "value": "[reference(concat('loop-', variables('count'))).outputs.collection.value]"
    }
}

قد يبدو من غير البديهي إرجاع output التكرار الأخير لقالب التحويل الخاص بنا إلى قالب الاستدعاء الخاص بنا، لأنه يبدو أننا قمنا بتخزينه في معلمتنا source . ومع ذلك، إنه التكرار الأخير لقالب التحويل الذي يحتوي على صفيف كامل من كائنات الخصائص المحولة، وهذا ما نريد إرجاعه.

أخيراً، دعنا نلقِ نظرة على كيفية استدعاء قالب المجمع من قالب الاتصال.

قالب الاتصال

يحدد قالب الاستدعاء معلمة واحدة تسمى networkSecurityGroupsSettings:

...
"parameters": {
    "networkSecurityGroupsSettings": {
        "type": "object"
    }
}

بعد ذلك، يحدد قالبنا متغيراً واحداً باسم collectorTemplateUri:

"variables": {
    "collectorTemplateUri": "[uri(deployment().properties.templateLink.uri, 'collector.template.json')]"
}

هذا هو URI لقالب المجمع الذي يستخدمه مورد القالب المرتبط لدينا:

{
    "apiVersion": "2020-06-01",
    "name": "collector",
    "type": "Microsoft.Resources/deployments",
    "properties": {
        "mode": "Incremental",
        "templateLink": {
            "uri": "[variables('collectorTemplateUri')]",
            "contentVersion": "1.0.0.0"
        },
        "parameters": {
            "source": {
                "value": "[parameters('networkSecurityGroupsSettings').securityRules]"
            },
            "transformTemplateUri": {
                "value": "[uri(deployment().properties.templateLink.uri, 'transform.json')]"
            }
        }
    }
}

نقوم بتمرير معلمتين إلى قالب المجمع:

  • source هي صفيف عنصر الخاصية. في مثالنا، إنها معلمة networkSecurityGroupsSettings الخاصة بنا.
  • transformTemplateUri هو المتغير الذي حددناه للتو باستخدام URI لقالب المجمع الخاص بنا.

أخيراً، يعين موردنا Microsoft.Network/networkSecurityGroups مباشرةً output لمورد القالب المرتبط collector إلى خاصية securityRules الخاصة به:

"resources": [
    {
        "apiVersion": "2020-05-01",
        "type": "Microsoft.Network/networkSecurityGroups",
        "name": "networkSecurityGroup1",
        "location": "[resourceGroup().location]",
        "properties": {
            "securityRules": "[reference('collector').outputs.result.value]"
        }
    }
],
"outputs": {
    "instance": {
        "type": "array",
        "value": "[reference('collector').outputs.result.value]"
    }
}

جرب القالب

يوج مثال قالب متاح على GitHub. لتوزيع القالب، قم باستنساخ المستودع وتشغيل أوامر Azure CLI التالية:

git clone https://github.com/mspnp/template-examples.git
cd template-examples/example4-collector
az group create --location <location> --name <resource-group-name>
az deployment group create -g <resource-group-name> \
    --template-uri https://raw.githubusercontent.com/mspnp/template-examples/master/example4-collector/deploy.json \
    --parameters deploy.parameters.json

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