Implementar um transformador de propriedade e um coletor em um modelo do Azure Resource Manager
No artigo Usar um objeto como um parâmetro em um modelo do Azure Resource Manager, você viu como armazenar valores de propriedade de recurso em um objeto e como aplicá-los a um recurso durante a implantação. Esta é uma maneira muito útil para gerenciar os parâmetros, mas requer que você mapeie as propriedades do objeto para propriedades de recursos sempre que você usar o objeto em seu modelo.
Para resolver esse problema, você pode implementar uma transformação de propriedade e um modelo de coletor que itere sua matriz de objeto e a transforme no esquema JSON do recurso.
Importante
Essa abordagem requer que você tenha uma compreensão profunda dos modelos e das funções do Resource Manager.
Vamos dar uma olhada em um exemplo que implementa um coletor de propriedade e um transformador para implantar um grupo de segurança de rede. O diagrama abaixo mostra como nossos modelos estão relacionados aos recursos nesses modelos:
Nosso modelo de chamada inclui dois recursos:
- Um link de modelo que invoca nosso modelo de coletor.
- O recurso de grupo de segurança de rede a ser implantado
Nosso modelo de coletor inclui dois recursos:
- um recurso de âncora
- Um link de modelo que invoca o modelo de transformação em um loop de cópia
Nosso modelo de transformação inclui apenas um recurso: um modelo vazio com uma variável que transforma nosso source
JSON no esquema JSON esperado por nosso recurso de grupo de segurança de rede no modelo principal.
Objeto Parameter
Usamos nosso securityRules
objeto de parâmetro de Usar objetos como parâmetros em um loop de cópia em um modelo do Azure Resource Manager. Nosso modelo de transformação transforma cada objeto na securityRules
matriz no esquema JSON esperado pelo recurso de grupo de segurança de rede em nosso modelo de chamada.
{
"$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"
}
]
}
}
}
}
Vamos examinar nosso modelo de transformação.
Modelo de Transformação
Nosso modelo de transformação inclui dois parâmetros que são passados do modelo de coletor:
source
é um objeto que recebe um dos objetos de valor de propriedade da matriz de propriedade. Em nosso exemplo, cada objeto dasecurityRules
matriz será transmitido um de cada vez.state
é uma matriz que recebe os resultados concatenados de todas as transformações anteriores. Esta é a coleção do JSON transformado.
Nossos parâmetros têm esta aparência:
{
"$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": []
}
},
Nosso modelo também define uma variável nomeada instance
que transforma nosso source
objeto no esquema JSON necessário:
"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]"
}
}
]
}
Por fim, o output
de nosso modelo concatena as transformações coletadas de nosso state
parâmetro com a transformação atual executada pela nossa variável instance
:
"resources": [],
"outputs": {
"collection": {
"type": "array",
"value": "[concat(parameters('state'), variables('instance'))]"
}
}
Em seguida, vamos dar uma olhada no nosso modelo de coletor para ver como ele informa os valores de parâmetro.
Modelo de coletor
Nosso modelo de coletor inclui três parâmetros:
source
é nossa matriz de objetos de parâmetro completa. Ele é informado pelo modelo de chamada. Ele tem o mesmo nome que osource
parâmetro no nosso modelo de transformação, mas há uma diferença importante que você já deve ter notado: embora essa seja a matriz completa, nós só informamos um elemento da matriz para o modelo de transformação por vez.transformTemplateUri
é o URI do nosso modelo de transformação. Nós o definimos como um parâmetro para reutilização do modelo.state
é uma matriz inicialmente vazia que podemos passar para o nosso modelo de transformação. Ele armazena a coleção de objetos de parâmetro transformados depois que o loop de cópia for concluído.
Nossos parâmetros têm esta aparência:
"parameters": {
"source": {
"type": "array"
},
"transformTemplateUri": {
"type": "string"
},
"state": {
"type": "array",
"defaultValue": []
}
}
Em seguida, definimos uma variável chamada count
. Seu valor é o comprimento da matriz de objetos de parâmetro source
:
"variables": {
"count": "[length(parameters('source'))]"
}
Nós o usamos para o número de iterações em nosso loop de cópia.
Agora vamos dar uma olhada em nossos recursos. Definimos dois recursos:
loop-0
é o recurso com base em zero para o loop de cópia.loop-
é concatenado com o resultado da funçãocopyIndex(1)
para gerar um nome exclusivo baseado em iteração para nosso recurso, começando com1
.
Nossos recursos têm esta aparência:
"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]" }
}
}
}
]
Vamos examinar mais detalhadamente os parâmetros que informamos para nosso modelo de transformação no modelo aninhado. Você se lembra de que nosso parâmetro source
passa o objeto atual na matriz de objetos de parâmetro source
. O parâmetro state
é onde a coleta acontece, porque ele pega a saída da iteração anterior do nosso loop de cópia e a passa para a iteração atual. Observe que a função reference()
usa a função copyIndex()
sem nenhum parâmetro para fazer referência ao name
nosso objeto de modelo vinculado anterior.
Por fim, o output
de nosso modelo retorna o output
da última iteração de nosso modelo de transformação:
"outputs": {
"result": {
"type": "array",
"value": "[reference(concat('loop-', variables('count'))).outputs.collection.value]"
}
}
Pode parecer contraintuitivo retornar o output
da última iteração de nosso modelo de transformação para nosso modelo de chamada porque ele aparece quando estamos armazenando-o em nosso parâmetro source
. No entanto, é a última iteração do nosso modelo de transformação que contém a matriz completa de objetos de propriedade transformados e que é o que queremos retornar.
Por fim, vamos dar uma olhada em como chamar o modelo de coletor do nosso modelo de chamada.
Modelo de chamada
Nosso modelo de chamada define um parâmetro único chamado networkSecurityGroupsSettings
:
...
"parameters": {
"networkSecurityGroupsSettings": {
"type": "object"
}
}
Em seguida, nosso modelo define uma variável denominada collectorTemplateUri
:
"variables": {
"collectorTemplateUri": "[uri(deployment().properties.templateLink.uri, 'collector.template.json')]"
}
Esse é o URI para o modelo de coletor que é usado pelo nosso recurso de modelo vinculado:
{
"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')]"
}
}
}
}
Passamos dois parâmetros para o modelo de coletor:
source
é a nossa matriz de objetos de propriedade. Em nosso exemplo, ele é nosso parâmetronetworkSecurityGroupsSettings
.transformTemplateUri
é a variável que acabamos de definir com o URI do nosso modelo de coletor.
Por fim, nosso recurso Microsoft.Network/networkSecurityGroups
atribui diretamente o output
do collector
vinculado o recurso de modelo para sua propriedade 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]"
}
}
Experimentar o modelo
Um modelo de exemplo está disponível no GitHub. Para implantar o modelo, clone o repositório e execute os seguintes comandos da CLI do Azure:
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
Próximas etapas
- Azure Resource Manager
- O que são modelos do ARM?
- Tutorial: Criar e implantar seu primeiro modelo do Resource Manager
- Tutorial: Adicionar um recurso ao modelo do ARM
- Práticas recomendadas para modelos do ARM
- Documentação do Azure Resource Manager
- Documentação do modelo ARM