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

Developing PowerShell modules for REST APIs – Part1

Over the years I have developed different PowerShell modules for different web APIs. I thought it would be a good idea to write a 2 series post about how you could go about to do this. This will be a 2 part blog series where we will run through the entire process of building a module for a REST API. I will try my best to keep this as simple as possible and leave more advanced stuff for a follow up post if the interest is there.What you needDepending on your experience with source control and PowerShell in general, you might want to use GIT or some other software repro for the code. In addition we are going to create a test REST API using the splendid UniversalDashboard PowerShell module created by Adam Driscoll. It is available on the PowershellGallery. Other prerequisites are built-in to Powershell. I will assume that you will be following along using at least PowerShell version 5 or greater.
What is HTTP metods for REST API.The primary or most common HTTP verbs used are POST, GET, PU…

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-CliXmlConvertTo-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 the same xml, however we …

Developing PowerShell modules for REST APIs – Part2

This is part 2 of the REST API blogpost. In part1 we successfully setup two REST API endpoints using the UniversalDashboard PowerShell module. In this part we are going to create a simple module that support some CRUD operation against our API. As we are trying to keep things as simple as possible, we will not use any fancy framework (like Plaster) to build our module. We are also going to skip a very important step you should familiarize yourself with, Pester tests. Lets get to it.


The moduleWe will build a module called FilesAPI. The module folder will look like this:



In the functions folder I have already added the 2 helper functions from part 1, Get-AuthorizationHeader and ConvertTo-Base64. The other folders are just placeholders for important stuff like classes, private functions that you do not want to make available for the module consumer and tests for Pester tests. For such a small module that we are going to create, one could argue that it is much easier to just add the functi…