Implementar um transformador e recoletor num modelo Azure Resource ManagerImplement a property transformer and collector in an Azure Resource Manager template

Na utilize um objeto como um parâmetro num modelo Azure Resource Manager, ficou a saber como armazenar valores de propriedade de recurso num objeto e aplicá-las a um recurso durante a implementação.In use an object as a parameter in an Azure Resource Manager template, you learned how to store resource property values in an object and apply them to a resource during deployment. Embora essa seja uma forma muito útil para gerir os seus parâmetros, ele ainda requer que mapeie as propriedades do objeto para propriedades de recursos sempre que usá-lo no seu modelo.While this is a very useful way to manage your parameters, it still requires you to map the object's properties to resource properties each time you use it in your template.

Para contornar este problema, pode implementar um modelo de transformação e o recoletor de propriedade que faz a iteração sua matriz de objeto e transforma-a no esquema JSON esperado pelo recurso.To work around this, you can implement a property transform and collector template that iterates your object array and transforms it into the JSON schema expected by the resource.

Importante

Essa abordagem requer que tenha uma compreensão profunda dos modelos do Resource Manager e funções.This approach requires that you have a deep understanding of Resource Manager templates and functions.

Vamos dar uma olhada em como podemos implementar um coletor de propriedade e um transformador com um exemplo que implementa uma grupo de segurança de rede.Let's take a look at how we can implement a property collector and transformer with an example that deploys a network security group. O diagrama abaixo mostra a relação entre nossos modelos e os nossos recursos dentro desses modelos:The diagram below shows the relationship between our templates and our resources within those templates:

arquitetura de recoletor e transformador da propriedade

Nosso modelo de chamada inclui dois recursos:Our calling template includes two resources:

  • uma ligação de modelo que invoca nosso modelo de recoletor.A template link that invokes our collector template.
  • Implementar o recurso de grupo de segurança rede.The network security group resource to deploy.

Nosso modelo de recoletor inclui dois recursos:Our collector template includes two resources:

  • uma âncora recursos.An anchor resource.
  • uma ligação de modelo que invoca o modelo de transformação num loop de cópia.A template link that invokes the transform template in a copy loop.

Nosso modelo de transformação inclui um único recurso: um modelo em branco com uma variável que transforma nossos source JSON para o esquema JSON esperado pelo nosso recurso de grupo de segurança de rede no modelo principal .Our transform template includes a single resource: an empty template with a variable that transforms our source JSON to the JSON schema expected by our network security group resource in the main template.

Objeto de parâmetroParameter object

Usaremos nosso securityRules objeto a partir do parâmetro objetos como parâmetros.We'll be using our securityRules parameter object from objects as parameters. Nosso modelo de transformação irá transformar a cada objeto na securityRules matriz no esquema JSON esperado pelo recurso de grupo de segurança de rede no nosso modelo chamado.Our transform template will transform each object in the securityRules array into the JSON schema expected by the network security group resource in our calling template.

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-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 dar uma olhada em nosso modelo de transformação primeiro.Let's look at our transform template first.

Transformar o modeloTransform template

Nosso modelo de transformação inclui dois parâmetros são passados dos modelo recoletor:Our transform template includes two parameters that are passed from the collector template:

  • source é um objeto que recebe um dos objetos de valor de propriedade da matriz de propriedade.source is an object that receives one of the property value objects from the property array. No nosso exemplo, cada objeto do "securityRules" matriz será passada um de cada vez.In our example, each object from the "securityRules" array will be passed in one at a time.
  • state é uma matriz que recebe os resultados concatenados de todas as transformações anteriores.state is an array that receives the concatenated results of all the previous transforms. Isso é uma coleção de JSON transformado.This is the collection of transformed JSON.

Nossos parâmetros tem esta aparência:Our parameters look like this:

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

Nosso modelo também define uma variável chamada instance.Our template also defines a variable named instance. Ele realiza a transformação real de nossa source objeto no esquema JSON necessário:It performs the actual transform of our source object into the required JSON schema:

  "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 do nosso modelo concatena as transformações recolhidas do nosso state parâmetro com a transformação atual realizada pelo nosso instance variável:Finally, the output of our template concatenates the collected transforms of our state parameter with the current transform performed by our instance variable:

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

Em seguida, vamos dar uma olhada em nosso modelo de recoletor para ver como ele passa nos nossos valores de parâmetros.Next, let's take a look at our collector template to see how it passes in our parameter values.

Modelo de recoletorCollector template

Nosso modelo de recoletor inclui três parâmetros:Our collector template includes three parameters:

  • source é nossa matriz de objeto do parâmetro completo.source is our complete parameter object array. É passado modelo de chamada.It's passed in by the calling template. Isso tem o mesmo nome que o source parâmetro no nosso modelo de transformação mas há uma diferença importante que deve ter já observado: Esta é a matriz completa, mas podemos passar apenas um elemento dessa matriz para o modelo de transformação cada vez.This has the same name as the source parameter in our transform template but there is one key difference that you may have already noticed: this is the complete array, but we only pass one element of this array to the transform template at a time.
  • transformTemplateUri é o URI do nosso modelo de transformação.transformTemplateUri is the URI of our transform template. Estamos definindo-lo como um parâmetro para reutilização de modelo.We're defining it as a parameter here for template reusability.
  • state é uma matriz inicialmente vazia que passamos para nosso modelo de transformação.state is an initially empty array that we pass to our transform template. Armazena a coleção de objetos do parâmetro transformados quando o loop de cópia for concluído.It stores the collection of transformed parameter objects when the copy loop is complete.

Nossos parâmetros tem esta aparência:Our parameters look like this:

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

Em seguida, definimos uma variável chamada count.Next, we define a variable named count. Seu valor é o período do source matriz de objeto de parâmetro:Its value is the length of the source parameter object array:

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

Como pode suspeitar, podemos utilizá-lo para o número de iterações no loop de cópia.As you might suspect, we use it for the number of iterations in our copy loop.

Agora vamos dar uma olhada em nossos recursos.Now let's take a look at our resources. Definimos dois recursos:We define two resources:

  • loop-0 é o recurso baseado em zero para nosso loop de cópia.loop-0 is the zero-based resource for our copy loop.
  • loop- é concatenado com o resultado do copyIndex(1) função para gerar um nome exclusivo para o nosso recurso, começando com baseadas em iterações 1.loop- is concatenated with the result of the copyIndex(1) function to generate a unique iteration-based name for our resource, starting with 1.

Nossos recursos de ter o seguinte aspeto:Our resources look like this:

  "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 dar uma olhada mais de perto os parâmetros que estamos passando para nosso modelo de transformação no modelo aninhado.Let's take a closer look at the parameters we're passing to our transform template in the nested template. Lembre-se anteriores que nossa source parâmetro passa o objeto atual no source matriz de objeto de parâmetro.Recall from earlier that our source parameter passes the current object in the source parameter object array. O state parâmetro é onde acontece a coleção, uma vez que demora a saída da iteração anterior do loop de cópia—tenha em atenção que o reference() funcionar utiliza o copyIndex() função sem parâmetros para fazer referência a name do nosso objeto de modelo ligado anterior—e passa-o para a iteração atual.The state parameter is where the collection happens, because it takes the output of the previous iteration of our copy loop—notice that the reference() function uses the copyIndex() function with no parameter to reference the name of our previous linked template object—and passes it to the current iteration.

Por fim, o output do nosso modelo devolve o output da última iteração de nossa transformação modelo:Finally, the output of our template returns the output of the last iteration of our transform template:

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

Possa parecer contraintuitivo para retornar a output da última iteração de nossa modelo de transformação para nosso modelo chamado porque parecia que foram armazená-los no nosso source parâmetro.It may seem counterintuitive to return the output of the last iteration of our transform template to our calling template because it appeared we were storing it in our source parameter. No entanto, lembre-se de que é a última iteração de nosso modelo de transformação que contém a matriz completa de objetos de propriedade transformados e que é o que queremos retornar.However, remember that it's the last iteration of our transform template that holds the complete array of transformed property objects, and that's what we want to return.

Por fim, vamos dar uma olhada em como chamar o modelo de recoletor da nossa modelo chamado.Finally, let's take a look at how to call the collector template from our calling template.

Modelo de chamadaCalling template

Nosso modelo de chamada define um parâmetro único chamado networkSecurityGroupsSettings:Our calling template defines a single parameter named networkSecurityGroupsSettings:

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

Em seguida, o nosso modelo define uma única variável com o nome collectorTemplateUri:Next, our template defines a single variable named collectorTemplateUri:

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

Como poderia esperar, este é o URI para o modelo de recoletor que será utilizado pelo nosso recurso de modelo ligado:As you would expect, this is the URI for the collector template that will be used by our linked template resource:

{
    "apiVersion": "2015-01-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 recoletor:We pass two parameters to the collector template:

  • source é nossa matriz de objeto de propriedade.source is our property object array. No nosso exemplo, é nosso networkSecurityGroupsSettings parâmetro.In our example, it's our networkSecurityGroupsSettings parameter.
  • transformTemplateUri é a variável que acabou de definir com o URI do nosso modelo de recoletor.transformTemplateUri is the variable we just defined with the URI of our collector template.

Por fim, nosso Microsoft.Network/networkSecurityGroups recursos diretamente atribui a output da collector ligado o recurso de modelo para sua securityRules propriedade:Finally, our Microsoft.Network/networkSecurityGroups resource directly assigns the output of the collector linked template resource to its securityRules property:

    {
      "apiVersion": "2015-06-15",
      "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 modeloTry the template

Um modelo de exemplo está disponível no GitHub.An example template is available on GitHub. Para implementar o modelo, clone o repositório e execute o seguinte [CLI do Azure] cli comandos:To deploy the template, clone the repo and run the following Azure CLI commands:

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