Parse ARM Template JSON Outputs In Azure Pipelines
It is common to have an ARM template deployment step as part of a pipeline/release in Azure DevOps. During this step resources are created or modified and we often want to export their names, URIs, IP addresses, keys for further use in the pipeline.
In this short article, we will take a look at how to parse outputs from an ARM template using PowerShell and Bash for both YAML-based and Classic release pipelines.
Contents:
- Defining Sample Outputs Section
- How To Set Pipeline Variable In Scripts
- Should I Use Bash Or PowerShell?
- YAML Pipeline
- Classic Release
Defining Sample Outputs Section
To make our discussion easier to follow, let’s define a very simple ARM template that returns someResourceUri
as part of outputs section.
Our goal is to retrieve someResourceUri
value in the pipeline and create corresponding pipeline variable so that we can use it in the next steps.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"resources": [],
"outputs": {
"someResourceUri": {
"type": "string",
"value": "https://example.com"
}
}
}
How To Set Pipeline Variable In Scripts
In order to use output values from ARM template deployment somewhere further in a pipeline, we need to be able to create pipeline variables from parsed values.
It can be achieved using task.setvariable
logging command. Logging command is a way for tasks and scripts to communicate with the agent, read more about syntax here.
There is a section in docs about setting variables in scripts, but to keep it short, refer to the example below where myVar
is the name of a pipeline variable, and someValue
is value =).
echo "##vso[task.setvariable variable=myVar]someValue"
We will use this functionality to set variables for both YAML pipelines and Classic releases.
Should I Use Bash Or PowerShell?
This decision is completely up to you, in this post we will look how to do it with either of them. But here are just a few notes:
- In examples we use pwsh - PowerShell Core which is the cross-platform version
- Microsoft-hosted agents usually have both pwsh and bash installed on both windows and linux agents, more information here
- If your agents are self-hosted, then choice is simple, just use what’s available
YAML Pipeline
Below is shown a sample ARM template deployment step, and its outputs we would like to parse.
NOTE: Outputs are assigned to a pipeline variable armOutputs
(deploymentOutputs setting).
- stage: DEV
jobs:
- job: Deploy
steps:
- task: AzureResourceManagerTemplateDeployment@3
inputs:
deploymentScope: 'Resource Group'
azureResourceManagerConnection: '...'
subscriptionId: '8a918a0a-b436-484b-8317-fa5bb7fb9f67'
action: 'Create Or Update Resource Group'
resourceGroupName: 'rg-contoso'
location: 'West US'
templateLocation: 'Linked artifact'
csmFile: 'template.json'
deploymentMode: 'Incremental'
deploymentOutputs: 'armOutputs'
PowerShell
So, this is the actual part where we parse output values. Note that the second step just logs the parsed value, so you won’t probably need it.
- ConvertFrom-Json is used to parse JSON
armOutputs
object is passed asARM_OUTPUTS
environment variable- Using pwsh task
- pwsh: |
$outputsObject = $env:ARM_OUTPUTS | ConvertFrom-Json
Write-Host "##vso[task.setvariable variable=someResourceUriPwsh]$($outputsObject.someResourceUri.value)"
displayName: 'Parse ARM deploymentOutputs | pwsh'
env:
ARM_OUTPUTS: $(armOutputs)
- script: echo $(someResourceUriPwsh)
displayName: 'Log someResourceUriPwsh'
Bash
Here is another way to parse outputs:
- jq is used for parsing JSON, ‘-r’ flag is passed to get value without quotes
armOutputs
object is passed asARM_OUTPUTS
environment variable- Using bash task
- bash: |
echo "##vso[task.setvariable variable=someResourceUriBash]$(echo $ARM_OUTPUTS | jq -r '.someResourceUri.value')"
displayName: 'Parse ARM deploymentOutputs | bash'
env:
ARM_OUTPUTS: $(armOutputs)
- script: echo $(someResourceUriBash)
displayName: 'Log someResourceUriBash'
Classic Release
The idea here is literally the same, the only difference is that it is now done through UI. We can use the same approach to set pipeline variables in scripts as illustrated above.
I will only briefly describe the steps since it’s quite similar to what we’ve already discussed before.
PowerShell
- Add PowerShell task
- Use inline script
- Check “Use PowerShell Core” option in “Advanced” section
- Set
ARM_OUTPUTS
variable to$(armOutputs)
in “Environment Variables” section
$outputsObject = $env:ARM_OUTPUTS | ConvertFrom-Json
Write-Host "##vso[task.setvariable variable=someResourceUriPwsh]$($outputsObject.someResourceUri.value)"
Bash
- Add Bash task
- Use inline script
- Set
ARM_OUTPUTS
variable to$(armOutputs)
in “Environment Variables” section
echo "##vso[task.setvariable variable=someResourceUriBash]$(echo $ARM_OUTPUTS | jq -r '.someResourceUri.value')"