diff --git a/internal/services/compute/orchestrated_virtual_machine_scale_set_resource.go b/internal/services/compute/orchestrated_virtual_machine_scale_set_resource.go index 82320f6993f6..b2d61d3eef10 100644 --- a/internal/services/compute/orchestrated_virtual_machine_scale_set_resource.go +++ b/internal/services/compute/orchestrated_virtual_machine_scale_set_resource.go @@ -795,12 +795,20 @@ func resourceOrchestratedVirtualMachineScaleSetUpdate(d *pluginsdk.ResourceData, provisionVMAgent := winConfig["provision_vm_agent"].(bool) patchAssessmentMode := winConfig["patch_assessment_mode"].(string) patchMode := winConfig["patch_mode"].(string) + hotpatchingEnabled := winConfig["hotpatching_enabled"].(bool) // If the image allows hotpatching the patch mode can only ever be AutomaticByPlatform. sourceImageReferenceRaw := d.Get("source_image_reference").([]interface{}) sourceImageId := d.Get("source_image_id").(string) isHotpatchEnabledImage = isValidHotPatchSourceImageReference(sourceImageReferenceRaw, sourceImageId) + // PatchSettings is required by PATCH API when running Hotpatch-compatible images. + if isHotpatchEnabledImage { + windowsConfig.PatchSettings.AssessmentMode = compute.WindowsPatchAssessmentMode(patchAssessmentMode) + windowsConfig.PatchSettings.PatchMode = compute.WindowsVMGuestPatchMode(patchMode) + windowsConfig.PatchSettings.EnableHotpatching = utils.Bool(hotpatchingEnabled) + } + if d.HasChange("os_profile.0.windows_configuration.0.enable_automatic_updates") || d.HasChange("os_profile.0.windows_configuration.0.provision_vm_agent") || d.HasChange("os_profile.0.windows_configuration.0.timezone") || @@ -838,7 +846,6 @@ func resourceOrchestratedVirtualMachineScaleSetUpdate(d *pluginsdk.ResourceData, // so while the attribute is exposed in VMSS it is hardcoded inside the images that // support hotpatching to always be enabled and cannot be set to false, ever. if d.HasChange("os_profile.0.windows_configuration.0.hotpatching_enabled") { - hotpatchingEnabled := winConfig["hotpatching_enabled"].(bool) if isHotpatchEnabledImage && !hotpatchingEnabled { return fmt.Errorf("when referencing a hotpatching enabled image the 'hotpatching_enabled' field must always be set to 'true', got %q", strconv.FormatBool(hotpatchingEnabled)) } diff --git a/internal/services/compute/orchestrated_virtual_machine_scale_set_resource_other_test.go b/internal/services/compute/orchestrated_virtual_machine_scale_set_resource_other_test.go index 28387750eb8c..ccffb2302891 100644 --- a/internal/services/compute/orchestrated_virtual_machine_scale_set_resource_other_test.go +++ b/internal/services/compute/orchestrated_virtual_machine_scale_set_resource_other_test.go @@ -163,6 +163,13 @@ func TestAccOrchestratedVirtualMachineScaleSet_AutomaticVMGuestPatchingHotpatchi ), }, data.ImportStep("os_profile.0.windows_configuration.0.admin_password"), + { + Config: r.windowsHotpatchingEnabledUpdate(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep("os_profile.0.windows_configuration.0.admin_password"), }) } @@ -504,6 +511,93 @@ resource "azurerm_orchestrated_virtual_machine_scale_set" "test" { `, data.RandomInteger, data.Locations.Primary, r.natgateway_template(data)) } +func (OrchestratedVirtualMachineScaleSetResource) windowsHotpatchingEnabledUpdate(data acceptance.TestData) string { + r := OrchestratedVirtualMachineScaleSetResource{} + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-OVMSS-%[1]d" + location = "%[2]s" +} + +%[3]s + +resource "azurerm_orchestrated_virtual_machine_scale_set" "test" { + name = "acctestOVMSS-%[1]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + sku_name = "Standard_F2s_v2" + + # Orchestrated VMSS allocation will timeout at service side due to extension, set instances to 0 to avoid the timeout + instances = 0 + + platform_fault_domain_count = 2 + + os_profile { + windows_configuration { + computer_name_prefix = "testvm" + admin_username = "myadmin" + admin_password = "Passwword1234" + + patch_mode = "AutomaticByPlatform" + hotpatching_enabled = true + } + } + + network_interface { + name = "TestNetworkProfile" + primary = true + + ip_configuration { + name = "TestIPConfiguration" + primary = true + subnet_id = azurerm_subnet.test.id + + public_ip_address { + name = "TestPublicIPConfiguration" + domain_name_label = "test-domain-label" + idle_timeout_in_minutes = 4 + } + } + } + + os_disk { + storage_account_type = "Standard_LRS" + caching = "ReadWrite" + } + + source_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2022-datacenter-azure-edition-core" + version = "latest" + } + + extension { + name = "HealthExtension" + publisher = "Microsoft.ManagedServices" + type = "ApplicationHealthWindows" + type_handler_version = "1.0" + auto_upgrade_minor_version_enabled = true + + settings = jsonencode({ + "protocol" = "http" + "port" = "80" + "requestPath" = "/" + }) + } + + tags = { + value = "update" + } +} +`, data.RandomInteger, data.Locations.Primary, r.natgateway_template(data)) +} + func (OrchestratedVirtualMachineScaleSetResource) windowsVMGuestPatching(data acceptance.TestData, patchMode string) string { r := OrchestratedVirtualMachineScaleSetResource{} return fmt.Sprintf(`