Dela via


Implementera en egenskapstransformator och insamlare i en Azure Resource Manager-mall

I artikeln Använda objekt som parametrar i en kopieringsloop i en Azure Resource Manager-mall kan du se hur du lagrar resursegenskapsvärden i ett objekt och hur du tillämpar dem på en resurs under distributionen. Det här är ett mycket användbart sätt att hantera parametrar, men du måste mappa egenskaperna för objektet till resursegenskaper varje gång du använder objektet i mallen.

För att undvika detta kan du implementera en egenskapstransformerings- och insamlarmall som itererar objektmatrisen och omvandlar den till JSON-schemat för resursen.

Viktigt

Den här metoden kräver att du har en djup förståelse för Resource Manager mallar och funktioner.

Nu ska vi titta på ett exempel som implementerar en egenskapsinsamlare och transformerare för att distribuera en nätverkssäkerhetsgrupp. Diagrammet nedan visar hur våra mallar är relaterade till resurserna i dessa mallar:

arkitektur för egenskapsinsamlare och transformerare

Vår samtalsmall innehåller två resurser:

  • En malllänk som anropar vår insamlarmall
  • Resursen för nätverkssäkerhetsgruppen som ska distribueras

Vår insamlarmall innehåller två resurser:

  • En fästpunktsresurs
  • En malllänk som anropar transformeringsmallen i en kopieringsloop

Vår transformeringsmall innehåller en enskild resurs: en tom mall med en variabel som omvandlar vår source JSON till det JSON-schema som förväntas av vår nätverkssäkerhetsgruppresurs i huvudmallen.

Parameterobjekt

Vi använder vårt securityRules parameterobjekt från Använd objekt som parametrar i en kopieringsloop i en Azure Resource Manager-mall. Vår transformeringsmall transformerar varje objekt i matrisen securityRules till det JSON-schema som förväntas av nätverkssäkerhetsgruppens resurs i vår anropande mall.

{
    "$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"
                    }
                ]
            }
        }
    }
}

Nu ska vi titta på vår transformeringsmall först.

Transformera mall

Vår transformeringsmall innehåller två parametrar som skickas från insamlingsmallen:

  • source är ett objekt som tar emot ett av egenskapsvärdeobjekten från egenskapsmatrisen. I vårt exempel skickas varje objekt från matrisen securityRules ett i taget.
  • state är en matris som tar emot de sammanfogade resultaten från alla tidigare transformeringar. Det här är samlingen med transformerad JSON.

Våra parametrar ser ut så här:

{
    "$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": []
        }
    },

Vår mall definierar också en variabel med namnet instance som omvandlar objektet source till det JSON-schema som krävs:

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

Slutligen sammanfogar mallen output de insamlade transformeringarna av parametern state med den aktuella transformeringen som utförs av variabeln instance :

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

Nu ska vi ta en titt på vår insamlarmall för att se hur den skickar våra parametervärden.

Insamlarmall

Vår insamlarmall innehåller tre parametrar:

  • source är vår fullständiga parameterobjektmatris. Den skickas av mallen för anrop. Den har samma namn som parametern source i vår transformeringsmall, men det finns en viktig skillnad: även om det är den fullständiga matrisen skickar vi bara ett matriselement i taget till transformeringsmallen.
  • transformTemplateUri är URI:n för vår transformeringsmall. Vi definierar den som en parameter för återanvändning av mallar.
  • state är en ursprungligen tom matris som vi skickar till vår transformeringsmall. Den lagrar samlingen av transformerade parameterobjekt när kopieringsloopen har slutförts.

Våra parametrar ser ut så här:

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

Därefter definierar vi en variabel med namnet count. Dess värde är längden på parameterobjektmatrisen source :

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

Vi använder den för antalet iterationer i vår kopieringsloop.

Nu ska vi ta en titt på våra resurser. Vi definierar två resurser:

  • loop-0 är den nollbaserade resursen för vår kopieringsloop.
  • loop- sammanfogas med resultatet av copyIndex(1) funktionen för att generera ett unikt iterationsbaserat namn för vår resurs, från och med 1.

Våra resurser ser ut så här:

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

Låt oss ta en närmare titt på de parametrar som vi skickar till vår transformeringsmall i den kapslade mallen. Kom ihåg att vår source parameter skickar det aktuella objektet i parameterobjektmatrisen source . Parametern state är där samlingen sker, eftersom den tar utdata från den tidigare iterationen av vår kopieringsloop och skickar den till den aktuella iterationen. Observera att reference() funktionen använder copyIndex() funktionen utan parameter för att referera name till vårt tidigare länkade mallobjekt.

Slutligen returnerar output mallen output för den senaste iterationen av transformeringsmallen:

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

Det kan verka kontraintuitivt att returnera den senaste iterationen output av vår transformeringsmall till vår anropsmall, eftersom det verkar som om vi lagrade den i parametern source . Det är dock den sista iterationen av vår transformeringsmall som innehåller den fullständiga matrisen med transformerade egenskapsobjekt, och det är vad vi vill returnera.

Slutligen ska vi ta en titt på hur du anropar insamlarmallen från vår samtalsmall.

Mall för samtal

Vår anropsmall definierar en enda parameter med namnet networkSecurityGroupsSettings:

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

Därefter definierar vår mall en enda variabel med namnet collectorTemplateUri:

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

Det här är URI:n för insamlarmallen som används av vår länkade mallresurs:

{
    "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')]"
            }
        }
    }
}

Vi skickar två parametrar till insamlarmallen:

  • source är vår egenskapsobjektmatris. I vårt exempel är det vår networkSecurityGroupsSettings parameter.
  • transformTemplateUri är den variabel som vi precis har definierat med URI:n för vår insamlarmall.

Slutligen tilldelar resursen Microsoft.Network/networkSecurityGroupsoutput direkt den collector länkade mallresursen till dess securityRules egenskap:

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

Prova mallen

Det finns en exempelmall på GitHub. Om du vill distribuera mallen klonar du lagringsplatsen och kör följande Azure CLI-kommandon :

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

Nästa steg