Retrieve ARM template output in PowerShell

Last month, I posted a sample Azure Resource Manager template that creates a virtual network as an example of how to use ARM child resources. The purpose of that post was primarily to suggest a style convention for using ARM child resources. In this post, I want to expand on a specific capability of ARM templates that I think is under-utilized using the template from that post.

In ARM templates, the outputs: {} section usually gets short shrift. At best, most examples you will find just let the Resource Manager write the default output to the console or to the resource group deployment. That’s a shame, since the outputs: {} section of a template can be extraordinarily useful when linking deployment of multiple resources, especially when coupled with PowerShell. Combining PowerShell and ARM templates delivers the best of both procedural and declarative infrastructure as code. I like to switch between them as needed. In fact, the example in this post and the previous one are excerpts of a PowerShell script that uses both the Azure PowerShell cmdlets and ARM templates to build a complex network infrastructure.

This post takes a look at how you might use outputs: {} to send ARM template results to a PowerShell script. First, the PowerShell script invokes the ARM template deployment. When that deployment completes, the resourceId of a newly created virtual network is specified in outputs: {}. That returned Vnet identifier is used to peer the new Vnet the network to another Vnet in a different subscription. This is done in PowerShell when the script resumes after ARM template deployment. (I’ve previously posted how to peer virtual networks using just ARM JSON, but it’s just much easier in PowerShell.)

Here’s what the outputs: {} section of the template looks like (once again, here’s the full Vnet template):

    "outputs": {
        "NewVnetResourceId": {
            "type": "string",
            "value": "[resourceId('Microsoft.Network/virtualNetworks',parameters('vnetName'))]"
        }
    }

There’s no mystery here — we are returning the resourceId of a virtual network. The question is, how do we access this resourceId in the PowerShell script that deployed this template?

The Azure documentation, incomplete as always, simply suggests you wait until after the script ends and retrieve the object using Get-AzResourceGroupDeployment. But that’s no help. We want the returned object while the script is running.

It turns out to be pretty easy to retrieve it. In a PowerShell script, you can assign the result of a deployment to a variable. The resulting variable is an object of type Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.PSResourceGroupDeployment. This object’s Outputs property is nothing more than a simple PowerShell hashtable (dictionary).

Here’s a screenshot showing this. I’ve paused script execution after the ARM template has been deployed to pipe the PowerShell $outputs variable to Get-Member. You can see from the object type and properties that $outputs.Output is just a hashtable. And we can use a simple foreach loop, iterating by the hashtable key value, to retrieve any or all of the returned values from the template deployment.

ARM template output in PowerShell
ARM template output in PowerShell (click to enlarge)

Here’s the PowerShell script shown in the screenshot.

$outputs = New-AzResourceGroupDeployment -Name BlogPostDeployment -ResourceGroupName RgBlogPostDemos -TemplateFile ./AzureResourceManagerChildResourcesStyleGuide.json -DeploymentDebugLogLevel All -Verbose -vnetName "BlogPostVnet" -VnetAddressSpace '10.172.12.0/22' -gatewaySubnetAddressPrefix "10.172.12.0/26" -subnets @(@{Name = "Subnet1"; addressPrefix = "10.172.12.64/26" }, @{Name = "Subnet2"; addressPrefix = "10.172.12.128/26" }) -region eastus
foreach ($key in $outputs.Outputs.keys) {
    if ($key -eq "NewVnetResourceId") {
        $NewVnetResourceId = $outputs.Outputs[$key].value
    }
}
"New Vnet ARM resource id is: $NewVnetResourceId"

This script invokes the virtual network creation template, passes parameters to it and then assigns the ARM template "outputs": [] value to $outputs. In turn, that PowerShell object contains a hashtable whose keys are the names of the JSON objects in the template’s "outputs": [] section. A simple PowerShell loop then retrieves a specific key and prints the results on the console.

I hope you find this useful.


Posted

in

,

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Exit mobile version