在 Azure Resource Manager 範本中實作屬性轉換器與收集器

Azure Resource Manager 範本的複製迴圈中使用物件作為參數,您可以看到如何在物件中儲存資源屬性值,以及如何在部署期間將它們套用至資源。 這是管理參數的非常有用方式,但每次您在範本中使用 物件時,都需要您將物件的屬性對應至資源屬性。

若要解決此問題,您可以實作屬性轉換和收集器範本,以逐一查看物件陣列,並將其轉換成資源的 JSON 架構。

重要

採取這種做法,您需要十分熟悉 Resource Manager 範本和函式。

讓我們看看實作屬性收集器和轉換器以部署 網路安全性群組的範例。 下圖顯示我們的範本如何與這些範本中的資源相關:

屬性收集器和轉換器架構

我們的呼叫範本有兩個資源:

  • 叫用收集器範本的範本連結
  • 要部署的網路安全性群組資源

我們的收集器範本有兩個資源:

  • 錨點資源
  • 在複製迴圈中叫用轉換範本的範本連結

我們的 轉換範本 包含單一資源:具有變數的空白範本,可將 source JSON 轉換成 主要範本中網路安全性群組資源預期的 JSON 架構。

參數物件

我們使用 Azure securityRulesResource Manager 範本中複製迴圈中的參數物件,將物件當做參數使用。 我們的轉換範本會將陣列中的每個物件轉換成呼叫範本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 資源將 collector 連結範本資源的 output 直接指派給其 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

下一步