In the first part of this series, you learned about PSArm — a PowerShell embedded DSL — that you can use to declaratively define your Azure infrastructure and generate an ARM template. PSArm, being a PowerShell DSL, supports PowerShell language constructs and builds the object model for ARM templates on top of PowerShell. So, if you are already familiar with PowerShell, writing ARM templates now will be as simple as writing another PowerShell script. So, how do you get started?
Installing PSArm
You can get PSArm module from the PowerShell gallery.
1 |
Install-Module -Name PSArm -AllowPrerelease |
You can also build module from the source code available on GitHub.
This module, when loaded, exports a bunch of functions and cmdlets.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
PS C:\sandbox\psarm> Get-Command -Module PSArm CommandType Name Version Source ----------- ---- ------- ------ Function add 0.1.0 PSArm Function and 0.1.0 PSArm Function array 0.1.0 PSArm Function base64 0.1.0 PSArm Function base64ToJson 0.1.0 PSArm Function base64ToString 0.1.0 PSArm Function bool 0.1.0 PSArm Function coalesce 0.1.0 PSArm Function concat 0.1.0 PSArm Function contains 0.1.0 PSArm Function copyIndex 0.1.0 PSArm Function createArray 0.1.0 PSArm Function createObject 0.1.0 PSArm Function dataUri 0.1.0 PSArm Function dataUriToString 0.1.0 PSArm Function dateTimeAdd 0.1.0 PSArm Function deployment 0.1.0 PSArm Function div 0.1.0 PSArm Function empty 0.1.0 PSArm Function endsWith 0.1.0 PSArm Function environment 0.1.0 PSArm Function equals 0.1.0 PSArm Function extensionResourceId 0.1.0 PSArm Function false 0.1.0 PSArm Function first 0.1.0 PSArm Function float 0.1.0 PSArm Function format 0.1.0 PSArm Function greater 0.1.0 PSArm Function greaterOrEquals 0.1.0 PSArm Function guid 0.1.0 PSArm Function if 0.1.0 PSArm Function indexOf 0.1.0 PSArm Function int 0.1.0 PSArm Function intersection 0.1.0 PSArm Function json 0.1.0 PSArm Function last 0.1.0 PSArm Function lastIndexOf 0.1.0 PSArm Function length 0.1.0 PSArm Function less 0.1.0 PSArm Function lessOrEquals 0.1.0 PSArm Function list 0.1.0 PSArm Function listAccountSas 0.1.0 PSArm Function listAdminKeys 0.1.0 PSArm Function listAuthKeys 0.1.0 PSArm Function listChannelWithKeys 0.1.0 PSArm Function listClusterAdminCredential 0.1.0 PSArm Function listConnectionStrings 0.1.0 PSArm Function listCredential 0.1.0 PSArm Function listCredentials 0.1.0 PSArm Function listKeys 0.1.0 PSArm Function listKeyValue 0.1.0 PSArm Function listPackage 0.1.0 PSArm Function listQueryKeys 0.1.0 PSArm Function listRawCallbackUrl 0.1.0 PSArm Function listSecrets 0.1.0 PSArm Function listServiceSas 0.1.0 PSArm Function listSyncFunctionTriggerStatus 0.1.0 PSArm Function max 0.1.0 PSArm Function min 0.1.0 PSArm Function mod 0.1.0 PSArm Function mul 0.1.0 PSArm Function newGuid 0.1.0 PSArm Function not 0.1.0 PSArm Function null 0.1.0 PSArm Function or 0.1.0 PSArm Function padLeft 0.1.0 PSArm Function parameters 0.1.0 PSArm Function providers 0.1.0 PSArm Function range 0.1.0 PSArm Function reference 0.1.0 PSArm Function replace 0.1.0 PSArm Function resourceGroup 0.1.0 PSArm Function resourceId 0.1.0 PSArm Function skip 0.1.0 PSArm Function split 0.1.0 PSArm Function startsWith 0.1.0 PSArm Function string 0.1.0 PSArm Function sub 0.1.0 PSArm Function subscription 0.1.0 PSArm Function subscriptionResourceId 0.1.0 PSArm Function substring 0.1.0 PSArm Function take 0.1.0 PSArm Function tenantResourceId 0.1.0 PSArm Function toLower 0.1.0 PSArm Function toUpper 0.1.0 PSArm Function trim 0.1.0 PSArm Function true 0.1.0 PSArm Function union 0.1.0 PSArm Function uniqueString 0.1.0 PSArm Function uri 0.1.0 PSArm Function uriComponent 0.1.0 PSArm Function uriComponentToString 0.1.0 PSArm Function utcNow 0.1.0 PSArm Function variables 0.1.0 PSArm Cmdlet ConvertFrom-ArmTemplate 0.1.0 PSArm Cmdlet ConvertTo-PSArm 0.1.0 PSArm Cmdlet New-PSArmDependsOn 0.1.0 PSArm Cmdlet New-PSArmEntry 0.1.0 PSArm Cmdlet New-PSArmFunctionCall 0.1.0 PSArm Cmdlet New-PSArmOutput 0.1.0 PSArm Cmdlet New-PSArmResource 0.1.0 PSArm Cmdlet New-PSArmSku 0.1.0 PSArm Cmdlet New-PSArmTemplate 0.1.0 PSArm Cmdlet Publish-PSArmTemplate 0.1.0 PSArm |
You can see that the exported functions are similar to what ARM template language offers.
PSArm Syntax Basics
A typical PSArm script for ARM template starts with the Arm
keyword. Within the Arm
body, you define each Azure resource using the Resource
keyword.
1 2 3 4 5 6 7 8 |
Arm { Resource "identifier" -Namespace "Microsoft.resource" -ApiVersion "resourceApiVersion" -Type "resourceType" { properties { "propertyName" "value" } } output "Output from deployment" } |
The Arm
, Resource
, and output
keywords are aliases defined in the module.
1 2 3 4 5 6 7 8 9 10 11 12 |
PS C:\sandbox\psarm> (Get-Alias).Where({$_.Source -eq 'PSArm'}) CommandType Name Version Source ----------- ---- ------- ------ Alias Arm -> New-PSArmTemplate 0.1.0 PSArm Alias ArmArray -> New-PSArmArray 0.1.0 PSArm Alias ArmElement -> New-PSArmElement 0.1.0 PSArm Alias ArmSku -> New-PSArmSku 0.1.0 PSArm Alias DependsOn -> New-PSArmDependsOn 0.1.0 PSArm Alias Output -> New-PSArmOutput 0.1.0 PSArm Alias RawCall -> New-PSArmFunctionCall 0.1.0 PSArm Alias RawEntry -> New-PSArmEntry 0.1.0 PSArm Alias Resource -> New-PSArmResource 0.1.0 PSArm |
With Arm
keyword, you can specify an optional Name
parameter which will be used as a name of the deployment within the template. For the resource definition, you use the Resource
keyword. You must specify a Name
to be used for the resource you want to provision, Namespace
of the resource, ApiVersion
, and Type
. As you enter arguments for these four parameters, you will see that PowerShell dynamically adds some more parameters based on the type of resource you intend to provision.

For example, as you see in the above screenshot, as soon as I added the Type
parameter and its argument, I get Kind
and Tags
as the dynamic parameters. You can, then, use the ArmSku
keyword to specify the SKU of the resource that you intend to provision. In case of a storage account, this can be set to Standard_LRS or any other supported value. Each Azure resource may need some more additional properties for resource provisioning and configuration. You can use the properties
keyword for this purpose. PSArm gives you the auto-completion of property names within the properties
block.

Finally, the output
keyword can be used to retrieve properties required from the deployed resource objects. This keyword takes Name
, Type
, and Value
as parameters.
First PSArm Script
Here is a complete PSArm script for provisioning a simple storage account.
1 2 3 4 5 6 7 8 9 |
Arm -Name myFirstTemplate -Body { Resource 'mypsarmsaccount' -Namespace 'Microsoft.Storage' -Type 'storageAccounts' -apiVersion '2019-06-01' -Kind 'StorageV2' -Location 'WestUS' { ArmSku 'Standard_LRS' Properties { accessTier 'Hot' } } Output 'storageResourceId' -Type 'string' -Value (ResourceId 'Microsoft.Storage/storageAccounts' (Concat 'myPsArmSaccount')) } |
Make a note of the ResourceId
and Concat
functions used along with the output
keyword. PSArm has public function parity with what is offered in ARM template language. You can save this script with a .psarm.ps1
extension and generate the ARM template JSON using the Publish-PSArmTemplate
cmdlet that PSArm module provides.
1 2 |
Publish-PSArmTemplate -Path .\firstTemplate.psarm.ps1 ` -OutFile .\firstTemplate.json -Force |
Here is the generated ARM template JSON for the PSArm script that you just built.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
{ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "psarm", "version": "0.1.0.0", "psarm-psversion": "5.1.19041.610", "templateHash": "5716551932369025750" } }, "resources": [ { "name": "myFirstTemplate", "type": "Microsoft.Resources/deployments", "apiVersion": "2019-10-01", "properties": { "mode": "Incremental", "expressionEvaluationOptions": { "scope": "inner" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "resources": [ { "name": "mypsarmsaccount", "apiVersion": "2019-06-01", "type": "Microsoft.Storage/storageAccounts", "kind": "StorageV2", "location": "WestUS", "sku": { "name": "Standard_LRS" }, "properties": { "accessTier": "Hot" } } ], "outputs": { "storageResourceId": { "type": "string", "value": "[resourceId('Microsoft.Storage/storageAccounts', concat('myPsArmSaccount'))]" } } } } } ] } |
This ARM template can be deployed using your favorite command line tool or using template deployment in Azure Portal.
When using Azure CLI,
1 |
az deployment group create --resource-group psarm --template-file .\firstTemplate.json |
When using Azure PowerShell,
1 |
New-AzResourceGroupDeployment -ResourceGroupName psarm -TemplateFile .\firstTemplate.json |
This is it. Congratulations. You just used PowerShell based DSL to generate and deploy an ARM template. In the next part of this series, you will learn more parameterizing PSArm scripts.