{"id":18960,"date":"2021-03-31T09:02:54","date_gmt":"2021-03-31T17:02:54","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/powershell\/?p=18960"},"modified":"2021-04-01T15:12:28","modified_gmt":"2021-04-01T23:12:28","slug":"announcing-the-preview-of-psarm","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/announcing-the-preview-of-psarm\/","title":{"rendered":"Announcing the preview of PSArm"},"content":{"rendered":"<h2>Announcing PSArm preview<\/h2>\n<p>Today, we are pleased to announce the first preview of a new experimental module that make it easier than ever for PowerShell users to create Azure Resource Manager (ARM) templates: <a href=\"https:\/\/github.com\/powershell\/psarm\">PSArm<\/a>.<\/p>\n<p>This module enables existing PowerShell users to author <a href=\"https:\/\/docs.microsoft.com\/azure\/azure-resource-manager\/templates\/overview\">ARM templates<\/a> using PowerShell syntax.<\/p>\n<p>Similar to <a href=\"https:\/\/docs.microsoft.com\/azure\/azure-resource-manager\/templates\/bicep-overview\">Azure Bicep<\/a>, PSArm is an independent module that creates the necessary ARM JSON template to deploy and configure Azure infrastructure in a PowerShell context.\nPSArm allows PowerShell users who are familiar with ARM to write complex deployment templates by mixing the declarative syntax of ARM with the imperative syntax of PowerShell.<\/p>\n<p>With PSArm, users can take advantage of PowerShell features when authoring ARM templates, such as:<\/p>\n<ul>\n<li>Variables, loops, conditionals, and pipelines<\/li>\n<li>Completion support<\/li>\n<li>Object-orientation, with an object model for ARM templates<\/li>\n<li>Parameter validation<\/li>\n<\/ul>\n<p>The PSArm module is still in early preview and is intended both as a demonstration both of how PowerShell can be leveraged to make ARM authoring easier and as a proof of concept for domain-specific languages (DSL) in PowerShell.\nAs a preview release, there may be breaking changes as development continues based on user feedback.<\/p>\n<h2>Bicep and PSArm<\/h2>\n<p>Bicep is Azure&#8217;s primary, supported Domain Specific Language (DSL) for deploying Azure resources declaratively. It aims to drastically simplify the ARM template authoring experience with a cleaner syntax, improved type safety, and better support for modularity and code re-use.<\/p>\n<p>PSArm is different from Bicep in that it is built for users who are already familiar and comfortable with PowerShell and its syntax.<\/p>\n<p>Additionally, Bicep is almost entirely a declarative language&#8211;meaning it represents a declaration of the end-state of Azure resources&#8211;while PSArm exposes the capabilities of PowerShell scripting alongside ARM resource declarations.<\/p>\n<p>We would also like to thank the Bicep team for their help and feedback as we developed PSArm.\u00a0 In fact, the template schema support in PSArm comes from the\u00a0<a href=\"https:\/\/github.com\/Azure\/bicep-types-az\">bicep-types-az<\/a> project, which also powers Bicep.<\/p>\n<h2>How can I start using this module?<\/h2>\n<p>PSArm has been published to the <a href=\"https:\/\/www.powershellgallery.com\/packages\/PSArm\">PowerShell Gallery<\/a>.\nThe module can also be built from source by following the instructions on the <a href=\"https:\/\/github.com\/powershell\/psarm\">PSArm GitHub repository<\/a>.<\/p>\n<p>Once you have the module installed you can begin authoring ARM templates with PowerShell.\nTo use PSArm, use the <code>Arm<\/code> keyword followed by a scriptblock.\nFrom within this scriptblock, PSArm provides contextual functionality.\nNote that the file name must end with the <code>.psarm.ps1<\/code> extension, for example <code>newStorageAccount.psarm.ps1<\/code>.<\/p>\n<p>The following example builds an ARM template to create a new storage account:<\/p>\n<pre><code class=\"powershell\">param(\r\n    [Parameter(Mandatory)]\r\n    [string]\r\n    $storageAccountName,\r\n\r\n    [Parameter(Mandatory)]\r\n    [string]\r\n    $location,\r\n\r\n    [Parameter()]\r\n    [string]\r\n    $accountType = 'Standard_LRS',\r\n\r\n    [Parameter()]\r\n    [string]\r\n    $kind = 'StorageV2',\r\n\r\n    [Parameter()]\r\n    [string]\r\n    $accessTier = 'Hot',\r\n\r\n    [Parameter()]\r\n    [string]\r\n    $minimumTLSVersion = 'TLS1_2',\r\n\r\n    [Parameter()]\r\n    [bool]\r\n    $supportsHTTPSTrafficOnly = 1,\r\n\r\n    [Parameter()]\r\n    [bool]\r\n    $allowBlobPublicAccess = 1,\r\n\r\n    [Parameter()]\r\n    [bool]\r\n    $allowSharedKeyAccess = 1\r\n)\r\n\r\nArm {\r\n\r\n    Resource $storageAccountName -Namespace 'Microsoft.Storage' -Type 'storageAccounts' -apiVersion '2019-06-01' -kind $kind -Location $location {\r\n        ArmSku $accountType\r\n        Properties {\r\n            accessTier $accessTier\r\n            minimumTLSVersion $minimumTLSVersion\r\n            supportsHTTPSTrafficOnly $supportsHTTPSTrafficOnly\r\n            allowBlobPublicAccess $allowBlobPublicAccess\r\n            allowSharedKeyAccess $allowSharedKeyAccess\r\n        }\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>Because PSArm scripts are just ordinary PowerShell scripts, you can use a <code>param<\/code> block at the top of a <code>.psarm.ps1<\/code> script as always to declare parameters, give them default values, mark them as mandatory, apply validation attributes like <code>[ValidateSet(...)]<\/code>, and so on.<\/p>\n<p>ARM template properties like <code>resources<\/code> and <code>outputs<\/code> are available in PSArm via keywords like <code>Resource<\/code> and <code>Output<\/code>. These keywords instantiate one resource or output instance at a time. These keywords can be used in any order.<\/p>\n<p>Within each resource are resource-level keywords specific to that resource type, which enable you to specify attributes available to that resource.\nFor resources with properties, a properties keyword specifies a block in which each resource property can be configured with its corresponding PowerShell keyword.\nThese keywords can be discovered with PowerShell completions.<\/p>\n<p>While using PSArm, PowerShell variables can be used removing the need for many ARM variable expressions, but there are a few cases where the ARM expressions may be necessary:\n&#8211; When a built-in ARM function needs to evaluated at deployment time, as in <code>resourceGroup()<\/code> or <code>utcNow()<\/code>\n&#8211; A variable is needed to be evaluated only once, as in <code>uniqueString()<\/code> to provide a hash value\n&#8211; When a secure input is required, as in the <code>securestring<\/code> parameter<\/p>\n<p>PSArm also provides ARM built-in expression functions as their own keywords. These functions allow users to use PowerShell syntax to express function application and member access.<\/p>\n<p>For more a more detailed explanation of the features and mechanisms available in PSArm, take a look at the README on the <a href=\"https:\/\/github.com\/powershell\/psarm\">PSArm GitHub repository<\/a>.<\/p>\n<p>With the above PSArm script saved to <code>newStorageAccount.psarm.ps1<\/code>, you can turn it into an ARM JSON template with the <code>Publish-PSArmTemplate<\/code> cmdlet:<\/p>\n<pre><code class=\"powershell\">Publish-PSArmTemplate -Path .\\newStorageAccount.psarm.ps1 -Parameters @{\r\n    storageAccountName = 'storageName'\r\n    location = 'location'\r\n}\r\n<\/code><\/pre>\n<p>This will create the equivalent ARM template in <code>.\\template.json<\/code>.\nThis file can then be deployed like any other ARM template, for example using Azure PowerShell:<\/p>\n<pre><code class=\"powershell\">New-AzResourceGroupDeployment -ResourceGroupName myRG -TemplateFile .\\template.json\r\n<\/code><\/pre>\n<p>The resulting ARM template can be viewed below:<\/p>\n<pre><code class=\"json\">{\r\n  \"$schema\": \"https:\/\/schema.management.azure.com\/schemas\/2019-04-01\/deploymentTemplate.json#\",\r\n  \"contentVersion\": \"1.0.0.0\",\r\n  \"metadata\": {\r\n    \"_generator\": {\r\n      \"name\": \"psarm\",\r\n      \"version\": \"0.1.0.0\",\r\n      \"psarm-psversion\": \"7.1.0\",\r\n      \"templateHash\": \"15035725580591843956\"\r\n    }\r\n  },\r\n  \"resources\": [\r\n    {\r\n      \"name\": \"test\",\r\n      \"type\": \"Microsoft.Resources\/deployments\",\r\n      \"apiVersion\": \"2019-10-01\",\r\n      \"properties\": {\r\n        \"mode\": \"Incremental\",\r\n        \"expressionEvaluationOptions\": {\r\n          \"scope\": \"inner\"\r\n        },\r\n        \"template\": {\r\n          \"$schema\": \"https:\/\/schema.management.azure.com\/schemas\/2019-04-01\/deploymentTemplate.json#\",\r\n          \"contentVersion\": \"1.0.0.0\",\r\n          \"resources\": [\r\n            {\r\n              \"name\": \"psarmtest\",\r\n              \"apiVersion\": \"2019-06-01\",\r\n              \"type\": \"Microsoft.Storage\/storageAccounts\",\r\n              \"kind\": \"StorageV2\",\r\n              \"location\": \"westus2\",\r\n              \"sku\": {\r\n                \"name\": \"Standard_LRS\"\r\n              },\r\n              \"properties\": {\r\n                \"accessTier\": \"Hot\",\r\n                \"minimumTlsVersion\": \"TLS1_2\",\r\n                \"supportsHttpsTrafficOnly\": true,\r\n                \"allowBlobPublicAccess\": true,\r\n                \"allowSharedKeyAccess\": true\r\n              }\r\n            }\r\n          ]\r\n        }\r\n      }\r\n    }\r\n  ]\r\n}\r\n<\/code><\/pre>\n<p>For more PSArm examples, see the <a href=\"https:\/\/github.com\/PowerShell\/PSArm\/tree\/master\/examples\">examples folder<\/a> in the PSArm repository.<\/p>\n<h2>Feedback and Support<\/h2>\n<p>Community feedback is essential to the development of PSArm and future experimentation.\nFeedback specifically on the conversion cmdlets, <code>ConvertFrom-ArmTemplate<\/code> and <code>ConvertTo-PSArm<\/code>, is appreciated.\nWhile there are no committed dates going forward, this is a quality driven project.\nIf significant changes come in based off of user feedback, a release will occur to verify the issues have been addressed.\nTo file an issue or to contribute, please visit the <a href=\"https:\/\/github.com\/powershell\/psarm\">PSArm GitHub repository<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We are pleased to announce the preview of PSArm, providing a domain-specific language embedded in PowerShell for Azure Resource Manager (ARM) templates.<\/p>\n","protected":false},"author":685,"featured_media":13641,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[3170,99,102,248,3171],"class_list":["post-18960","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","tag-announcement","tag-azure","tag-azure-resource-manager","tag-powershell","tag-psarm"],"acf":[],"blog_post_summary":"<p>We are pleased to announce the preview of PSArm, providing a domain-specific language embedded in PowerShell for Azure Resource Manager (ARM) templates.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/18960","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/685"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=18960"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/18960\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=18960"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=18960"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=18960"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}