2
votes

I want to disable "Windows Updates" for ARM template-based VM deployments. I found a relevant setting enableAutomaticUpdates in a recent Microsoft.Compute provider schema. But I did not find any ARM template using this setting. I searched a couple of Azure Quickstart templates related to Windows VM deployments - but none of them intends to control the behaviour of Windows Update service at provisioning time. I am aware of options available with CLASSIC deployment model, but I am explicitly looking for a solution using Azure Resource Manager Deployment model.

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",

...

{
  "apiVersion": "2015-06-15",
  "type": "Microsoft.Compute/virtualMachines",
  "name": "[parameters('vmName')]",
  "location": "[parameters('vmLocation')]",
  "tags": {
    "displayName": "VirtualMachine"
  },
  "dependsOn": [
    "[concat('Microsoft.Storage/storageAccounts/', parameters('vmStorageAccountName'))]",
    "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
  ],
  "properties": {
    "hardwareProfile": {
      "vmSize": "[parameters('vmSize')]"
    },
    "osProfile": {
      "computerName": "[parameters('vmName')]",
      "adminUsername": "[parameters('adminUsername')]",
      "adminPassword": "[parameters('adminPassword')]"
    },
    "windowsConfiguration": {
      "enableAutomaticUpdates": false        
    },
    ...

My attempt to use the property windowsConfiguration in my existing ARM template leads to a failed deployment and this error message (shown in Azure Portal).

Could not find member 'windowsConfiguration' on object of type 'Properties'. Path 'properties.windowsConfiguration', line 1, position 259. (Code: BadRequest)

When I upgrade Microsoft.Compute to version 2015-08-01, trying to refer the schema containing configuration property enableAutomaticUpdates, the VM deployment fails with this error message. Obviously I am doing something wrong.

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",

...

{
  "apiVersion": "2015-08-01",
  "type": "Microsoft.Compute/virtualMachines",
  "name": "[parameters('vmName')]",
  "location": "[parameters('vmLocation')]",
  "tags": {
    "displayName": "VirtualMachine"
  },
  "dependsOn": [
    "[concat('Microsoft.Storage/storageAccounts/', parameters('vmStorageAccountName'))]",
    "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
  ],
  "properties": {
    "hardwareProfile": {
      "vmSize": "[parameters('vmSize')]"
    },
    "osProfile": {
      "computerName": "[parameters('vmName')]",
      "adminUsername": "[parameters('adminUsername')]",
      "adminPassword": "[parameters('adminPassword')]"
    },
    "windowsConfiguration": {
      "enableAutomaticUpdates": false        
    },
    ...

No registered resource provider found for location 'West Europe' and API version '2015-08-01' for type 'virtualMachines'. The supported api-versions are '2015-05-01-preview, 2015-06-15, 2016-03-30'. The supported locations are 'eastus, eastus2, westus, centralus, northcentralus, southcentralus, northeurope, westeurope, eastasia, southeastasia, japaneast, japanwest, australiaeast, australiasoutheast, brazilsouth'. (Code: NoRegisteredProviderFound)

I am asking for some guidance how to write ARM templates that use Azure Compute Provider schema version 2015-08-01 to disable Windows Updates at provisioning time. My .NET solution uses Azure SDK 2.7.1.

2

2 Answers

3
votes

I was pretty close to the solution. I just misunderstood the schema. According to this part of the schema windowsConfiguration is part of osProfile. If the ARM template is written like this Azure Resource Manager is understanding what I want and disables AutomaticUpdates at provisioning time.

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",

...

{
  "apiVersion": "2015-06-15",
  "type": "Microsoft.Compute/virtualMachines",
  "name": "[parameters('vmName')]",
  "location": "[resourceGroup().location]",
  "tags": {
    "displayName": "VirtualMachine"
  },
  "dependsOn": [
    "[concat('Microsoft.Storage/storageAccounts/', parameters('vmStorageAccountName'))]",
    "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
  ],
  "properties": {
    "hardwareProfile": {
      "vmSize": "[parameters('vmSize')]"
    },
    "osProfile": {
      "computerName": "[parameters('vmName')]",
      "adminUsername": "[parameters('adminUsername')]",
      "adminPassword": "[parameters('adminPassword')]",
      "windowsConfiguration": {
        "enableAutomaticUpdates": false        
      }
    },
    ...

The incredible tool Resource Explorer in Azure Portal shows the current configuration for the given resource. As you can see EnableAutomaticUpdates is set to false.

{
    "properties": {
        "vmId": "10400cdd-26be-4be4-99d8-2d5c22d96911",
        "hardwareProfile": {
            "vmSize": "Standard_D2"
        },
        "storageProfile": {
            "imageReference": {
                "publisher": "MicrosoftWindowsServer",
                "offer": "WindowsServer",
                "sku": "2012-R2-Datacenter",
                "version": "latest"
            },
            "osDisk": {
                "osType": "Windows",
                "name": "osdisk",
                "createOption": "FromImage",
                "vhd": {
                    "uri": "this_is_not_for_public_use"
                },
                "caching": "ReadWrite"
            },
            "dataDisks": []
        },
        "osProfile": {
            "computerName": "this_is_not_for_public_use",
            "adminUsername": "this_is_not_for_public_use",
            "windowsConfiguration": {
                "provisionVMAgent": true,
                "enableAutomaticUpdates": false
            },
            "secrets": []
        },
        "networkProfile": {
            "networkInterfaces": [
                {
                    "id": "this_is_not_for_public_use/providers/Microsoft.Network/networkInterfaces/ComputeNode15-Nic"
                }
            ]
        },
        "provisioningState": "Creating"
    },
    "id": "this_is_not_for_public_use/providers/Microsoft.Compute/virtualMachines/this_is_not_for_public_use",
    "name": "this_is_not_for_public_use",
    "type": "Microsoft.Compute/virtualMachines",
    "location": "westeurope",
    "tags": {
        "displayName": "VirtualMachine"
    }
}

And I changed the template to use the location of the resource group - a useful option in most case. Thanks to Martyn C for providing this hint and for valuable feedback pushing me into the right direction.

1
votes

Looking at the above error message, you are passing the location as "West Europe" when it should be "westeurope". Region names should be passed all lower case.

You can just use the location of the resource group using the following line in your JSON template, "location": "[resourceGroup().location]" which would be the better practice.