Deconstructing JSON: Anatomy of a VM

While the Azure VM on has two official dependencies, the storage account and the network interface, there are a variety of properties that you need to gather or determine ahead of time in order for your deployment to be successful.  If you were doing the manual creation of the VM in the Portal, the properties would be the parts you’d have to enter while shuffling through all the blades.  Let’s shuffle less blades….

With the VM template, we start out like every other resource, requiring a type, name, API version and location for deployment.  You can see the two lines that call the two dependencies.

 {
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Compute/virtualMachines",
      "name": "[variables('vmName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[concat('Microsoft.Storage/storageAccounts/', parameters('newStorageAccountName'))]",
        "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
      ],

When you get into the properties, you can see where everything comes together with a variety of profiles for hardware, the operating system, storage, networking and diagnostics.  When deploying via PowerShell, you’ll get prompted to enter the Admin username and password manually.

To fill in the variables for the image reference part of the storage profile, you can use some handy PowerShell to query Azure for the existing image names.  (I’ll put that at the bottom of the post.)

       "properties": {
        "hardwareProfile": {
          "vmSize": "[variables('vmSize')]"
        },
        "osProfile": {
          "computerName": "[variables('vmName')]",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[parameters('adminPassword')]"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "[variables('imagePublisher')]",
            "offer": "[variables('imageOffer')]",
            "sku": "[parameters('windowsOSVersion')]",
            "version": "latest"
          },
          "osDisk": {
            "name": "osdisk",
            "vhd": {
              "uri": "[concat('https://',parameters('newStorageAccountName'),'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/',variables('OSDiskName'),'.vhd')]"
            },
            "caching": "ReadWrite",
            "createOption": "FromImage"
          }
          },
            
          "networkProfile": {
          "networkInterfaces": [             
        {
              "id": "[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]"
            }
          ]
        },
          "diagnosticsProfile": {
          "bootDiagnostics": {
             "enabled": "true",
             "storageUri": "[concat('https://',parameters('newStorageAccountName'),'.blob.core.windows.net')]"
          }
        }
        }

The PowerShell for the image references: these lines will return the current images available for Windows Server. Be sure to pick the location you intend to use, because some image skus have limited regions and change the publisher name as needed if Windows Server isn’t what you are looking to deploy.

 Get-AzureRmVMImagePublisher -Location "West US"

Get-AzureRmVMImageOffer -Location "West US" -PublisherName MicrosoftWindowsServer

Get-AzureRmVMImageSku -Location "West US" -PublisherName MicrosoftWindowsServer -Offer WindowsServer

You’ll find the full template to deploy this one VM here: https://github.com/techbunny/Templates/tree/master/smallcloudlab