Skip to main content

Something completely different – PoshARM

I needed a project for my Xmas holiday and I needed something remotely work related. Thus the dubious PoshARM PowerShell module was born and brought to life during my Xmas holiday. Simply put it is a module that lets you build – for now – simple Azure Resource Manager (ARM) templates with PowerShell . 

The module can also import templates from a file or from the clipboard/string. Your partial template or ready made template can be exported as a PowerShell script. This blog post will walk you through how to use it and the features that is currently implemented. 



Update 08.02.2017:

The module is now published to the PowerShellGallery (https://www.powershellgallery.com/packages/posharm). It is still in beta version, however test coverage have increased and some bugs have been squashed during the testing. Also help is present, however somewhat lacking here and there.

Update 18.01.2017:

The module is now on GitHub. Here is the link to the repro (PoshARM on GitHub)



What is a ARM template?

It is a text file, or more correctly a JSON text file. Here is a sample template which is empty:

image

The ARM template is an input to the Azure Resource Manager which is responsible for deploying you resource definition (your ARM template) onto an Azure Subscription. There are multiple ways you can make or build your template:


  • Any pure text editor (Notepad, Notepad++)
  • Visual Studio
  • Visual Studio Code
  • PoshARM (this module)

To summarize an ARM template consists of these main building blocks:

  • Parameters
  • Variables
  • Resources
  • Outputs

In addition you should also have a metadata.json file associated with your template. You can find the complete Microsoft documentation of an ARM template on this link: Authoring ARM-templates


Why PoshARM?

Good question. In my experience this will probably not be the primary way of creating an ARM template for the professionals. For them is will probably be quicker to manually copy/paste and edit the template in an text editor or in Visual Studio. Trouble is when your template expands, it can get quite big. In addition I have yet to say hello to any IT-pro (with very few exceptions) that embrace and understand big JSON files, much less IT-pros that build their own ARM templates. If only a single person find it useful or any part of this module is useful, I will be happy.



Module status

This is a public alpha preview. There are bugs in the module and it is not feature complete in any way. Currently I have Pester coverage for most of the cmdlets, however the current ARM-template test file is just to create a simple VM in Azure and it contains 6 resources, some parameters and variables. As always, help is missing everywhere and this is the reason I have not published it to Powershell Gallery yet.

There are currently no cmdlet for working with the template outputs property. It is handled and imported if you use the Import-ARMtemplate cmdlet, however it will be missing if you export it.




ARM Variables

To interact with variables we have these cmdlets:

  • Get-ARMvariable
  • New-ARMvariable
  • Add-ARMvariable
  • Get-ARMvariableScript
  • Set-ARMvariable

Creating a new variable is straight forward and we can pipe the output to Add-ARMvariable to add it to the template:




Set-ARMvariable and Get-ARMvariable cmdlets implements a dynamic parameter for the Name of the variable. This makes it impossible to set or get the value of a variable if it does not exists:

image


ARM Parameters

A parameter have many more properties than a variable, however you need to specify a Name and the Type of the parameter. These are the cmdlets we have:


  • Get-ARMparameter
  • Get-ARMparameterScript
  • New-ARMparameter
  • Add-ARMparameter
  • Set-ARMparameter

Creating a parameter for adminUserName can be as simple as this:




As with the variable cmdlets, we have a dynamic parameter for the name both for Get-ARMparameter and Set-ARMparameter.



ARM Resources

This is where it gets rather complicated. The resources property of the ARM template, expects an array of resources which in turn can have nested resources, which again can have nested resources. As you would expect, we have a few cmdlets to work with resources as well:


  • Get-ARMresourceList
  • Update-ARMresourceList
  • Get-ARMresourceScript
  • New-ARMresource
  • Add-ARMresource

Get-ARMresourceList provides dynamic resource type parameter for New-ARMresource. The Update-ARMresourceList cmdlet is used to update the cached version of the resource providers that is available in Azure. Currently the cached resource list is saved in the module path (.\Data\AllResources.json), however it should probably be moved to AppData.

Creating a new resource is straight forward. Currently it does not support lookup of variables and parameters, however that feature could be added later. Here is an example that creates an new Storage Account on Azure:


The New-ARMresource cmdlet implements a Dynamic parameter named Type. The value for this parameter is generated by the Get-ARMresourceList command. 



ARM template metadata


Each template should have some metadata that help to identify the template. There is a Set-ARMmetadata cmdlet that will create the metadata.json file for you. Here is an example metadata.json file:




Importing existing ARM templates

On GitHub you can find loads of quick starter templates that you can modify and update. It would be pretty useless if this module did not let you import these templates and work with them. The Import-ARMtemplate will import an template from the clipboard/string or from a file on your computer. Here is how you can use it:



ARM template


For working with ARM templates, we have the following cmdlets:


  • Get-ARMtemplate
  • Get-ARMtemplateScript
  • New-ARMtemplate

The New-ARMtemplate cmdlet will create a new empty ARM template in the current Powershell session. Currently it will overwrite the current template if you have started creating one. This will change and will require you to specify the Force parameter if a template exists.

Get-ARMtemplate executed without any parameters will return the template which is stored in a module variable called $Script:Template. It also have 2 switch parameters:


  • Get-ARMtemplate –AsJSON
  • Get-ARMtempalte –AsHashTableString

The hashtable string version is easier on the eye compared to the JSON version, however that depends on your JSON experience level and your hashtable fondness level.



Helper functions

There are two helper functions available in the module. Both of them are used heavily in the Script cmdlets which we will talk about next.


ConvertTo-Hash

If you have worked with Powershell it should be pretty simple to understand what this cmdlet does. It converts an Inputobject to an hashtable, that is it actually outputs a ordered hashtable. It will chew through the Inputobject and create an ordered hashtable even for nested objects and arrays. Lets take it for a spin:


image



Out-HashString

Give this cmdlet an hashtable or an ordered hashtable an it will output the text version of it that you can paste into a Powershell host and execute. Let’s use the $fileObject hashtabel and see if we can get back the text representation of the object:

image

Yes, there it is with proper indention and everything.




Get-ARM*Script

You may have noticed that I have added a cmdlet for each property that have the Get-ARM*Script name syntax. The purpose of those cmdlets are to generate the Powershell script for each property in the template. Here is how you use it:

In the example we have created 2 variables, a parameter and a resource. These have been added to our template as we have moved along. Now we introduce the Get-ARMtemplateScript cmdlet which will give you the template as a script. Here are the commands we have executed:



Now we are going to run Get-ARMtemplateScript and see what we get back:

image

There we have it. We just created a ARM template with Powershell and converted the template back to a Powershell script. This also works with imported templates which enables you to copy snippets of code to create templates. The observant reader may spot the bug in the screenshot above. The SKU key is “System.Collections.Hashtable” which is not correct. Did I mention that it is not ready yet? Well it is not, but it is almost working.



Planned features

Depending on the reception of the module, I have planned some enhancements for the module:


  • Add help
  • Improve Pester coverage
  • Add cmdlets for creating outputs
  • Add support for template functions and keywords ([variables()], [parameters()], [concat()], [resourceId()] etc)
  • Template linking

Please contact me if you have other suggestions or ideas. I cannot think of everything.



Final thoughts


There is a very small amount of job left to make this module work at the current functional level. Please leave feedback here on my blog or reach out to me on Twitter (@ToreGroneng). The module will be published on PowerShellGallery.com and the link to the repro is here (link to PoshARM).

Cheers

Tore

Comments

  1. Do you have this up on github ?

    ReplyDelete
    Replies
    1. hi, yes is was uploaded to GitHub today, however it is still work in progress. I am in the process of refactoring some of the code. That is almost done, however I am also updating the pester tests. The link to the repro on GitHub is in the last sentence :-)

      Cheers

      Tore

      Delete
  2. Hi Tore! Any chance you can post an example of a template setup with a child resource? For example, a web site with a slot of a resource with a lock. Thanks.

    ReplyDelete
    Replies
    1. Hi, that is one idea. Thank you. The module still need a little love, but it is getting there.

      Delete

Post a Comment

Popular posts from this blog

Serialize data with PowerShell

Currently I am working on a big new module. In this module, I need to persist data to disk and reprocess them at some point even if the module/PowerShell session was closed. I needed to serialize objects and save them to disk. It needed to be very efficient to be able to support a high volume of objects. Hence I decided to turn this serializer into a module called HashData. Other Serializing methods In PowerShell we have several possibilities to serialize objects. There are two cmdlets you can use which are built in: Export-CliXml ConvertTo-JSON Both are excellent options if you do not care about the size of the file. In my case I needed something lean and mean in terms of the size on disk for the serialized object. Lets do some tests to compare the different types: (Hashdata.Object.ps1) You might be curious why I do not use the Export-CliXML cmdlet and just use the [System.Management.Automation.PSSerializer]::Serialize static method. The static method will generate t

Toying with audio in powershell

Controlling mute/unmute and the volume on you computer with powershell. Add-Type -TypeDefinition @' using System.Runtime.InteropServices; [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IAudioEndpointVolume { // f(), g(), ... are unused COM method slots. Define these if you care int f(); int g(); int h(); int i(); int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext); int j(); int GetMasterVolumeLevelScalar(out float pfLevel); int k(); int l(); int m(); int n(); int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext); int GetMute(out bool pbMute); } [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IMMDevice { int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume aev); } [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), Inte

Creating Menus in Powershell

I have created another Powershell module. This time it is about Console Menus you can use to ease the usage for members of your oranization. It is available on GitHub and published to the PowershellGallery . It is called cliMenu. Puppies This is a Controller module. It uses Write-Host to create a Menu in the console. Some of you may recall that using Write-Host is bad practice. Controller scripts and modules are the exception to this rule. In addition with WMF5 Write-Host writes to the Information stream in Powershell, so it really does not matter anymore. Design goal I have seen to many crappy menus that is a mixture of controller script and business logic. It is in essence a wild west out there, hence my ultimate goal is to create something that makes it as easy as possible to create a menu and change the way it looks. Make it easy to build Menus and change them Make it as "declarative" as possible Menus The module supports multiple Men