Azure Resource Manager templates are complex JSON structures. The main complaint about these templates is the difficultly to read and work with. The language service shipped with VSCode supports comments and a better syntax highlighting. However, to get a quick idea of the templates content a readable documentation is needed. In this post we are going to have a look how we can address these issue.

Document Infrastructure As Code

What if we could take a given ARM template and create readable documentation that we can publish in our Wiki? PowerShells native ability to work with json files can come in handy to query and filter a json file.

To address the lack of readability, we can gather a few requirements based on common task:

  • See what kind of Parameters are needed for a given template.
  • Check what kind of resources a given ARM template is deploying
  • See the outputs a given template returns

Implementation

We can use PowerShell to return a list of resources by simply returning the resources type and name of an ARM template.

For demo purposes I am using azuredeploy.json

# New-Readme.ps1
param (
  $Path = (Join-Path $PSScriptRoot "azuredeploy.json")
)
 # Test for template presence
$null = Test-Path $Path -ErrorAction Stop

# Test if arm template content is readable
$text = Get-Content $Path -Raw -ErrorAction Stop

# Convert the ARM template to an Object

$json = ConvertFrom-Json $text -ErrorAction Stop

# Resources
$json.resources.type
$json.resources.name

String Building the Documentation

Now that we have traverse the list of properties we can use PowerShell to create a string that is similar to markdown, plain text, or any other markup language. In this demo implementation I am going to stick to Markdown. An easy way to get started and learn markdown is the interactive markdowntutorial.

Markdown can be used with Github to create documentation for your project through Github Pages or as means to document your repository. Azure DevOps uses Markdown to publish the content in form of a Wiki. Automating the documentation and the creation of Markdown comes in handy.

As Markdown is very light weight we can leverage simple strings to create our documentation. To better visualize the parameters, resource and outputs of an ARM template a table might be a feasible option for display.

We can use the strings to output into a file or concat them into a bigger string incorporating more information. For now this is a good baseline to extend on it. The output can be saved to a file using Out-File.

./New-Readme.ps1 | Out-File Documentation.md

## Parameters
| Parameter Name           | Parameter Type | Parameter Description                                                                           | Parameter DefaultValue     |
| ------------------------ | -------------- | ----------------------------------------------------------------------------------------------- | -------------------------- |
| location                 | string         | Azure location for deployment                                                                   | [resourceGroup().location] |
| networkAcls              | string         | Optional. Networks ACLs Object, this value contains IPs to whitelist and/or Subnet information. |                            |
| resourceName             | string         | Name of the Data Lake Storage Account                                                           |                            |
| storageAccountAccessTier | string         | Optional. Storage Account Access Tier.                                                          | Hot                        |
| storageAccountSku        | string         | Optional. Storage Account Sku Name.                                                             | Standard_ZRS               |

## Resources

| Resource Type                     | Resource Name                | Resource Comment                      |
| --------------------------------- | ---------------------------- | ------------------------------------- |
| Microsoft.Storage/storageAccounts | [parameters('resourceName')] | Azure Data Lake Gen 2 Storage Account |

## Outputs

| Output Name   | Output Value | Output Type |
| ------------- | ------------ | ----------- |
| componentName | string       |             |
| resourceID    | string       |             |

To demonstrate the output the generated documentation is displayed below.

Example Output

Parameters

Parameter Name Parameter Type Parameter Description Parameter DefaultValue
location string Azure location for deployment [resourceGroup().location]
networkAcls string Optional. Networks ACLs Object, this value contains IPs to whitelist and/or Subnet information.  
resourceName string Name of the Data Lake Storage Account  
storageAccountAccessTier string Optional. Storage Account Access Tier. Hot
storageAccountSku string Optional. Storage Account Sku Name. Standard_ZRS

Resources

Resource Type Resource Name Resource Comment
Microsoft.Storage/storageAccounts [parameters(‘resourceName’)] Azure Data Lake Gen 2 Storage Account

Outputs

Output Name Output Value Output Type
componentName string  
resourceID string  

Parameters

You can use a ParameterFile generator that will generate a valid Parameter File base on a given ARm template for you. In Generate Azure Resource Manager Templates Parameter files using PowerShell you can find an implementation guide.

A quick way to let your users create a parameter file is by given an example. To generate a simple parameter structure for documentation purposes this one-liner comes in handy:

# Create azuredeploy.parameters.json
$json.parameters | get-member -MemberType NoteProperty | % { [pscustomobject]@{  $_.Name = @{ Value = $json.parameters.($_.Name).DefaultValue  } } } | ConvertTo-Json  #| clip

You can store the output (on Windows) to the clipboard by passing it to the | clip function. Or add this line to the Readme generator to allow your Readme users to copy paste the blueprint.

[
  {
    "location": {
      "Value": "[resourceGroup().location]"
    }
  },
  {
    "networkAcls": {
      "Value": null
    }
  },
  {
    "resourceName": {
      "Value": null
    }
  },
  {
    "storageAccountAccessTier": {
      "Value": "Hot"
    }
  },
  {
    "storageAccountSku": {
      "Value": "Standard_ZRS"
    }
  }
]

Remarks

Table of Content