From 601c4a0363e029a24c34ee016eeb7d7fc868956d Mon Sep 17 00:00:00 2001 From: Zhenhua Hu Date: Tue, 12 Sep 2023 19:56:50 +0800 Subject: [PATCH 01/10] support `automatic_upgrade_enabled` --- ...nux_virtual_machine_resource_other_test.go | 9 ++++---- internal/services/compute/virtual_machine.go | 22 +++++++++++++++---- ...ows_virtual_machine_resource_other_test.go | 9 ++++---- .../r/linux_virtual_machine.html.markdown | 2 ++ .../r/windows_virtual_machine.html.markdown | 2 ++ 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/internal/services/compute/linux_virtual_machine_resource_other_test.go b/internal/services/compute/linux_virtual_machine_resource_other_test.go index 09925f63a320..61c62a20ea98 100644 --- a/internal/services/compute/linux_virtual_machine_resource_other_test.go +++ b/internal/services/compute/linux_virtual_machine_resource_other_test.go @@ -1593,10 +1593,11 @@ resource "azurerm_linux_virtual_machine" "test" { } gallery_application { - version_id = azurerm_gallery_application_version.test2.id - order = 2 - configuration_blob_uri = azurerm_storage_blob.test2.id - tag = "app2" + version_id = azurerm_gallery_application_version.test2.id + automatic_upgrade_enabled = true + order = 2 + configuration_blob_uri = azurerm_storage_blob.test2.id + tag = "app2" } } `, r.otherGalleryApplicationTemplate(data), data.RandomInteger) diff --git a/internal/services/compute/virtual_machine.go b/internal/services/compute/virtual_machine.go index 64e935f6313b..36c95ed45280 100644 --- a/internal/services/compute/virtual_machine.go +++ b/internal/services/compute/virtual_machine.go @@ -504,6 +504,12 @@ func VirtualMachineGalleryApplicationSchema() *pluginsdk.Schema { ValidateFunc: galleryapplicationversions.ValidateApplicationVersionID, }, + "automatic_upgrade_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + // Example: https://mystorageaccount.blob.core.windows.net/configurations/settings.config "configuration_blob_uri": { Type: pluginsdk.TypeString, @@ -537,6 +543,7 @@ func expandVirtualMachineGalleryApplication(input []interface{}) *[]compute.VMGa for _, v := range input { packageReferenceId := v.(map[string]interface{})["version_id"].(string) + automaticUpgradeEnabled := v.(map[string]interface{})["automatic_upgrade_enabled"].(bool) configurationReference := v.(map[string]interface{})["configuration_blob_uri"].(string) order := v.(map[string]interface{})["order"].(int) tag := v.(map[string]interface{})["tag"].(string) @@ -546,6 +553,7 @@ func expandVirtualMachineGalleryApplication(input []interface{}) *[]compute.VMGa ConfigurationReference: utils.String(configurationReference), Order: utils.Int32(int32(order)), Tags: utils.String(tag), + EnableAutomaticUpgrade: utils.Bool(automaticUpgradeEnabled), } out = append(out, *app) @@ -564,6 +572,7 @@ func flattenVirtualMachineGalleryApplication(input *[]compute.VMGalleryApplicati for _, v := range *input { var packageReferenceId, configurationReference, tag string var order int + var automaticUpgradeEnabled bool if v.PackageReferenceID != nil { packageReferenceId = *v.PackageReferenceID @@ -573,6 +582,10 @@ func flattenVirtualMachineGalleryApplication(input *[]compute.VMGalleryApplicati configurationReference = *v.ConfigurationReference } + if v.EnableAutomaticUpgrade != nil { + automaticUpgradeEnabled = *v.EnableAutomaticUpgrade + } + if v.Order != nil { order = int(*v.Order) } @@ -582,10 +595,11 @@ func flattenVirtualMachineGalleryApplication(input *[]compute.VMGalleryApplicati } app := map[string]interface{}{ - "version_id": packageReferenceId, - "configuration_blob_uri": configurationReference, - "order": order, - "tag": tag, + "version_id": packageReferenceId, + "automatic_upgrade_enabled": automaticUpgradeEnabled, + "configuration_blob_uri": configurationReference, + "order": order, + "tag": tag, } out = append(out, app) diff --git a/internal/services/compute/windows_virtual_machine_resource_other_test.go b/internal/services/compute/windows_virtual_machine_resource_other_test.go index fe23769b2107..4a7dc108ac7c 100644 --- a/internal/services/compute/windows_virtual_machine_resource_other_test.go +++ b/internal/services/compute/windows_virtual_machine_resource_other_test.go @@ -1947,10 +1947,11 @@ resource "azurerm_windows_virtual_machine" "test" { } gallery_application { - version_id = azurerm_gallery_application_version.test2.id - order = 2 - configuration_blob_uri = azurerm_storage_blob.test2.id - tag = "app2" + version_id = azurerm_gallery_application_version.test2.id + automatic_upgrade_enabled = true + order = 2 + configuration_blob_uri = azurerm_storage_blob.test2.id + tag = "app2" } } `, r.otherGalleryApplicationTemplate(data)) diff --git a/website/docs/r/linux_virtual_machine.html.markdown b/website/docs/r/linux_virtual_machine.html.markdown index 84c2e7768043..fd3c701ef876 100644 --- a/website/docs/r/linux_virtual_machine.html.markdown +++ b/website/docs/r/linux_virtual_machine.html.markdown @@ -262,6 +262,8 @@ A `gallery_application` block supports the following: * `version_id` - (Required) Specifies the Gallery Application Version resource ID. +* `automatic_upgrade_enabled` - (Optional) Whether the version will be automatically updated for the VM when a new Gallery Application version is available in PIR/SIG. Defaults to `false`. + * `configuration_blob_uri` - (Optional) Specifies the URI to an Azure Blob that will replace the default configuration for the package if provided. * `order` - (Optional) Specifies the order in which the packages have to be installed. Possible values are between `0` and `2,147,483,647`. diff --git a/website/docs/r/windows_virtual_machine.html.markdown b/website/docs/r/windows_virtual_machine.html.markdown index d326f7879cc0..db06a38ef752 100644 --- a/website/docs/r/windows_virtual_machine.html.markdown +++ b/website/docs/r/windows_virtual_machine.html.markdown @@ -261,6 +261,8 @@ A `gallery_application` block supports the following: * `version_id` - (Required) Specifies the Gallery Application Version resource ID. +* `automatic_upgrade_enabled` - (Optional) Whether the version will be automatically updated for the VM when a new Gallery Application version is available in PIR/SIG. Defaults to `false`. + * `configuration_blob_uri` - (Optional) Specifies the URI to an Azure Blob that will replace the default configuration for the package if provided. * `order` - (Optional) Specifies the order in which the packages have to be installed. Possible values are between `0` and `2,147,483,647`. From 6323ca463d7b775287cbbaab4af3961630e3007a Mon Sep 17 00:00:00 2001 From: Zhenhua Hu Date: Wed, 13 Sep 2023 13:59:47 +0800 Subject: [PATCH 02/10] support `treat_failure_as_deployment_failure_enabled` --- ...nux_virtual_machine_resource_other_test.go | 19 +++++++------- internal/services/compute/virtual_machine.go | 25 ++++++++++++++----- ...ows_virtual_machine_resource_other_test.go | 19 +++++++------- .../r/linux_virtual_machine.html.markdown | 4 ++- .../r/windows_virtual_machine.html.markdown | 4 ++- 5 files changed, 45 insertions(+), 26 deletions(-) diff --git a/internal/services/compute/linux_virtual_machine_resource_other_test.go b/internal/services/compute/linux_virtual_machine_resource_other_test.go index 61c62a20ea98..ee61bfb2fee7 100644 --- a/internal/services/compute/linux_virtual_machine_resource_other_test.go +++ b/internal/services/compute/linux_virtual_machine_resource_other_test.go @@ -1593,11 +1593,12 @@ resource "azurerm_linux_virtual_machine" "test" { } gallery_application { - version_id = azurerm_gallery_application_version.test2.id - automatic_upgrade_enabled = true - order = 2 - configuration_blob_uri = azurerm_storage_blob.test2.id - tag = "app2" + version_id = azurerm_gallery_application_version.test2.id + automatic_upgrade_enabled = true + order = 2 + configuration_blob_uri = azurerm_storage_blob.test2.id + tag = "app2" + treat_failure_as_deployment_failure_enabled = true } } `, r.otherGalleryApplicationTemplate(data), data.RandomInteger) @@ -1695,8 +1696,8 @@ resource "azurerm_gallery_application_version" "test" { } manage_action { - install = "[install command]" - remove = "[remove command]" + install = "echo install" + remove = "echo remove" } target_region { @@ -1725,8 +1726,8 @@ resource "azurerm_gallery_application_version" "test2" { } manage_action { - install = "[install command]" - remove = "[remove command]" + install = "echo install" + remove = "echo remove" } target_region { diff --git a/internal/services/compute/virtual_machine.go b/internal/services/compute/virtual_machine.go index 36c95ed45280..8dea20a960bb 100644 --- a/internal/services/compute/virtual_machine.go +++ b/internal/services/compute/virtual_machine.go @@ -530,6 +530,12 @@ func VirtualMachineGalleryApplicationSchema() *pluginsdk.Schema { Optional: true, ValidateFunc: validation.StringIsNotEmpty, }, + + "treat_failure_as_deployment_failure_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, }, }, } @@ -547,13 +553,15 @@ func expandVirtualMachineGalleryApplication(input []interface{}) *[]compute.VMGa configurationReference := v.(map[string]interface{})["configuration_blob_uri"].(string) order := v.(map[string]interface{})["order"].(int) tag := v.(map[string]interface{})["tag"].(string) + treatFailureAsDeploymentFailureEnabled := v.(map[string]interface{})["treat_failure_as_deployment_failure_enabled"].(bool) app := &compute.VMGalleryApplication{ - PackageReferenceID: utils.String(packageReferenceId), - ConfigurationReference: utils.String(configurationReference), - Order: utils.Int32(int32(order)), - Tags: utils.String(tag), - EnableAutomaticUpgrade: utils.Bool(automaticUpgradeEnabled), + PackageReferenceID: utils.String(packageReferenceId), + ConfigurationReference: utils.String(configurationReference), + Order: utils.Int32(int32(order)), + Tags: utils.String(tag), + EnableAutomaticUpgrade: utils.Bool(automaticUpgradeEnabled), + TreatFailureAsDeploymentFailure: utils.Bool(treatFailureAsDeploymentFailureEnabled), } out = append(out, *app) @@ -572,7 +580,7 @@ func flattenVirtualMachineGalleryApplication(input *[]compute.VMGalleryApplicati for _, v := range *input { var packageReferenceId, configurationReference, tag string var order int - var automaticUpgradeEnabled bool + var automaticUpgradeEnabled, treatFailureAsDeploymentFailureEnabled bool if v.PackageReferenceID != nil { packageReferenceId = *v.PackageReferenceID @@ -594,12 +602,17 @@ func flattenVirtualMachineGalleryApplication(input *[]compute.VMGalleryApplicati tag = *v.Tags } + if v.TreatFailureAsDeploymentFailure != nil { + treatFailureAsDeploymentFailureEnabled = *v.TreatFailureAsDeploymentFailure + } + app := map[string]interface{}{ "version_id": packageReferenceId, "automatic_upgrade_enabled": automaticUpgradeEnabled, "configuration_blob_uri": configurationReference, "order": order, "tag": tag, + "treat_failure_as_deployment_failure_enabled": treatFailureAsDeploymentFailureEnabled, } out = append(out, app) diff --git a/internal/services/compute/windows_virtual_machine_resource_other_test.go b/internal/services/compute/windows_virtual_machine_resource_other_test.go index 4a7dc108ac7c..d5370d06b644 100644 --- a/internal/services/compute/windows_virtual_machine_resource_other_test.go +++ b/internal/services/compute/windows_virtual_machine_resource_other_test.go @@ -1947,11 +1947,12 @@ resource "azurerm_windows_virtual_machine" "test" { } gallery_application { - version_id = azurerm_gallery_application_version.test2.id - automatic_upgrade_enabled = true - order = 2 - configuration_blob_uri = azurerm_storage_blob.test2.id - tag = "app2" + version_id = azurerm_gallery_application_version.test2.id + automatic_upgrade_enabled = true + order = 2 + configuration_blob_uri = azurerm_storage_blob.test2.id + tag = "app2" + treat_failure_as_deployment_failure_enabled = true } } `, r.otherGalleryApplicationTemplate(data)) @@ -2045,8 +2046,8 @@ resource "azurerm_gallery_application_version" "test" { } manage_action { - install = "[install command]" - remove = "[remove command]" + install = "echo install" + remove = "echo remove" } target_region { @@ -2074,8 +2075,8 @@ resource "azurerm_gallery_application_version" "test2" { } manage_action { - install = "[install command]" - remove = "[remove command]" + install = "echo install" + remove = "echo remove" } target_region { diff --git a/website/docs/r/linux_virtual_machine.html.markdown b/website/docs/r/linux_virtual_machine.html.markdown index fd3c701ef876..3019c2e06f93 100644 --- a/website/docs/r/linux_virtual_machine.html.markdown +++ b/website/docs/r/linux_virtual_machine.html.markdown @@ -262,7 +262,7 @@ A `gallery_application` block supports the following: * `version_id` - (Required) Specifies the Gallery Application Version resource ID. -* `automatic_upgrade_enabled` - (Optional) Whether the version will be automatically updated for the VM when a new Gallery Application version is available in PIR/SIG. Defaults to `false`. +* `automatic_upgrade_enabled` - (Optional) Specifies whether the version will be automatically updated for the VM when a new Gallery Application version is available in PIR/SIG. Defaults to `false`. * `configuration_blob_uri` - (Optional) Specifies the URI to an Azure Blob that will replace the default configuration for the package if provided. @@ -270,6 +270,8 @@ A `gallery_application` block supports the following: * `tag` - (Optional) Specifies a passthrough value for more generic context. This field can be any valid `string` value. +* `treat_failure_as_deployment_failure_enabled` - (Optional) Specifies whether any failure for any operation in the VmApplication will fail the deployment of the VM. Defaults to `false`. + --- An `identity` block supports the following: diff --git a/website/docs/r/windows_virtual_machine.html.markdown b/website/docs/r/windows_virtual_machine.html.markdown index db06a38ef752..13834e16ac49 100644 --- a/website/docs/r/windows_virtual_machine.html.markdown +++ b/website/docs/r/windows_virtual_machine.html.markdown @@ -261,7 +261,7 @@ A `gallery_application` block supports the following: * `version_id` - (Required) Specifies the Gallery Application Version resource ID. -* `automatic_upgrade_enabled` - (Optional) Whether the version will be automatically updated for the VM when a new Gallery Application version is available in PIR/SIG. Defaults to `false`. +* `automatic_upgrade_enabled` - (Optional) Specifies whether the version will be automatically updated for the VM when a new Gallery Application version is available in PIR/SIG. Defaults to `false`. * `configuration_blob_uri` - (Optional) Specifies the URI to an Azure Blob that will replace the default configuration for the package if provided. @@ -269,6 +269,8 @@ A `gallery_application` block supports the following: * `tag` - (Optional) Specifies a passthrough value for more generic context. This field can be any valid `string` value. +* `treat_failure_as_deployment_failure_enabled` - (Optional) Specifies whether any failure for any operation in the VmApplication will fail the deployment of the VM. Defaults to `false`. + --- An `identity` block supports the following: From f428c0d1d1284541133077fc0ecd51dabc3843f1 Mon Sep 17 00:00:00 2001 From: Zhenhua Hu Date: Wed, 13 Sep 2023 16:35:03 +0800 Subject: [PATCH 03/10] support `vm_agent_platform_updates_enabled` --- .../compute/linux_virtual_machine_resource.go | 22 +++++ ...nux_virtual_machine_resource_other_test.go | 94 ++++++++++++++++++ .../windows_virtual_machine_resource.go | 30 +++++- ...ows_virtual_machine_resource_other_test.go | 96 ++++++++++++++++++- .../r/linux_virtual_machine.html.markdown | 2 + .../r/windows_virtual_machine.html.markdown | 2 + 6 files changed, 239 insertions(+), 7 deletions(-) diff --git a/internal/services/compute/linux_virtual_machine_resource.go b/internal/services/compute/linux_virtual_machine_resource.go index f33b4569c80a..2969d6b34aeb 100644 --- a/internal/services/compute/linux_virtual_machine_resource.go +++ b/internal/services/compute/linux_virtual_machine_resource.go @@ -340,6 +340,12 @@ func resourceLinuxVirtualMachine() *pluginsdk.Resource { ValidateFunc: computeValidate.VirtualMachineScaleSetID, }, + "vm_agent_platform_updates_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + "vtpm_enabled": { Type: pluginsdk.TypeBool, Optional: true, @@ -440,6 +446,7 @@ func resourceLinuxVirtualMachineCreate(d *pluginsdk.ResourceData, meta interface computerName = id.Name } disablePasswordAuthentication := d.Get("disable_password_authentication").(bool) + vmAgentPlatformUpdatesEnabled := d.Get("vm_agent_platform_updates_enabled").(bool) location := azure.NormalizeLocation(d.Get("location").(string)) identityRaw := d.Get("identity").([]interface{}) identity, err := expandVirtualMachineIdentity(identityRaw) @@ -492,6 +499,7 @@ func resourceLinuxVirtualMachineCreate(d *pluginsdk.ResourceData, meta interface AllowExtensionOperations: utils.Bool(allowExtensionOperations), LinuxConfiguration: &compute.LinuxConfiguration{ DisablePasswordAuthentication: utils.Bool(disablePasswordAuthentication), + EnableVMAgentPlatformUpdates: utils.Bool(vmAgentPlatformUpdatesEnabled), ProvisionVMAgent: utils.Bool(provisionVMAgent), SSH: &compute.SSHConfiguration{ PublicKeys: &sshKeys, @@ -875,6 +883,7 @@ func resourceLinuxVirtualMachineRead(d *pluginsdk.ResourceData, meta interface{} if config := profile.LinuxConfiguration; config != nil { d.Set("disable_password_authentication", config.DisablePasswordAuthentication) d.Set("provision_vm_agent", config.ProvisionVMAgent) + d.Set("vm_agent_platform_updates_enabled", config.EnableVMAgentPlatformUpdates) flattenedSSHKeys, err := FlattenSSHKeys(config.SSH) if err != nil { @@ -1256,6 +1265,19 @@ func resourceLinuxVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interface } } + if d.HasChange("vm_agent_platform_updates_enabled") { + shouldUpdate = true + if update.VirtualMachineProperties.OsProfile == nil { + update.VirtualMachineProperties.OsProfile = &compute.OSProfile{} + } + + if update.VirtualMachineProperties.OsProfile.LinuxConfiguration == nil { + update.VirtualMachineProperties.OsProfile.LinuxConfiguration = &compute.LinuxConfiguration{} + } + + update.VirtualMachineProperties.OsProfile.LinuxConfiguration.EnableVMAgentPlatformUpdates = utils.Bool(d.Get("vm_agent_platform_updates_enabled").(bool)) + } + if d.HasChange("patch_mode") { shouldUpdate = true patchSettings := &compute.LinuxPatchSettings{} diff --git a/internal/services/compute/linux_virtual_machine_resource_other_test.go b/internal/services/compute/linux_virtual_machine_resource_other_test.go index ee61bfb2fee7..422b353208fc 100644 --- a/internal/services/compute/linux_virtual_machine_resource_other_test.go +++ b/internal/services/compute/linux_virtual_machine_resource_other_test.go @@ -93,6 +93,30 @@ func TestAccLinuxVirtualMachine_otherAllowExtensionOperationsUpdatedWithoutVmAge }) } +func TestAccLinuxVirtualMachine_otherVmAgentPlatformUpdates(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine", "test") + r := LinuxVirtualMachineResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.otherVmAgentPlatformUpdatesEnabled(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("vm_agent_platform_updates_enabled").HasValue("true"), + ), + }, + data.ImportStep(), + { + Config: r.otherVmAgentPlatformUpdatesDisabled(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("vm_agent_platform_updates_enabled").HasValue("false"), + ), + }, + data.ImportStep(), + }) +} + func TestAccLinuxVirtualMachine_otherExtensionsTimeBudget(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine", "test") r := LinuxVirtualMachineResource{} @@ -1146,6 +1170,76 @@ resource "azurerm_linux_virtual_machine" "test" { `, r.template(data), data.RandomInteger) } +func (r LinuxVirtualMachineResource) otherVmAgentPlatformUpdatesEnabled(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_linux_virtual_machine" "test" { + name = "acctestVM-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_F2" + admin_username = "adminuser" + vm_agent_platform_updates_enabled = true + + network_interface_ids = [ + azurerm_network_interface.test.id, + ] + + admin_ssh_key { + username = "adminuser" + public_key = local.first_public_key + } + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } +} +`, r.template(data), data.RandomInteger) +} + +func (r LinuxVirtualMachineResource) otherVmAgentPlatformUpdatesDisabled(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_linux_virtual_machine" "test" { + name = "acctestVM-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_F2" + admin_username = "adminuser" + network_interface_ids = [ + azurerm_network_interface.test.id, + ] + + admin_ssh_key { + username = "adminuser" + public_key = local.first_public_key + } + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } +} +`, r.template(data), data.RandomInteger) +} + func (r LinuxVirtualMachineResource) otherExtensionsTimeBudget(data acceptance.TestData, duration string) string { return fmt.Sprintf(` %s diff --git a/internal/services/compute/windows_virtual_machine_resource.go b/internal/services/compute/windows_virtual_machine_resource.go index 6d379077a861..4bcd31a67db2 100644 --- a/internal/services/compute/windows_virtual_machine_resource.go +++ b/internal/services/compute/windows_virtual_machine_resource.go @@ -369,6 +369,12 @@ func resourceWindowsVirtualMachine() *pluginsdk.Resource { ValidateFunc: computeValidate.VirtualMachineScaleSetID, }, + "vm_agent_platform_updates_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + "platform_fault_domain": { Type: pluginsdk.TypeInt, Optional: true, @@ -506,6 +512,8 @@ func resourceWindowsVirtualMachineCreate(d *pluginsdk.ResourceData, meta interfa sourceImageId := d.Get("source_image_id").(string) sourceImageReference := expandSourceImageReference(sourceImageReferenceRaw, sourceImageId) + vmAgentPlatformUpdatesEnabled := d.Get("vm_agent_platform_updates_enabled").(bool) + winRmListenersRaw := d.Get("winrm_listener").(*pluginsdk.Set).List() winRmListeners := expandWinRMListener(winRmListenersRaw) @@ -528,9 +536,10 @@ func resourceWindowsVirtualMachineCreate(d *pluginsdk.ResourceData, meta interfa ComputerName: utils.String(computerName), AllowExtensionOperations: utils.Bool(allowExtensionOperations), WindowsConfiguration: &compute.WindowsConfiguration{ - ProvisionVMAgent: utils.Bool(provisionVMAgent), - EnableAutomaticUpdates: utils.Bool(enableAutomaticUpdates), - WinRM: winRmListeners, + ProvisionVMAgent: utils.Bool(provisionVMAgent), + EnableAutomaticUpdates: utils.Bool(enableAutomaticUpdates), + EnableVMAgentPlatformUpdates: utils.Bool(vmAgentPlatformUpdatesEnabled), + WinRM: winRmListeners, }, Secrets: secrets, }, @@ -917,8 +926,8 @@ func resourceWindowsVirtualMachineRead(d *pluginsdk.ResourceData, meta interface } d.Set("enable_automatic_updates", config.EnableAutomaticUpdates) - d.Set("provision_vm_agent", config.ProvisionVMAgent) + d.Set("vm_agent_platform_updates_enabled", config.EnableVMAgentPlatformUpdates) assessmentMode := string(compute.WindowsPatchAssessmentModeImageDefault) bypassPlatformSafetyChecksOnUserScheduleEnabled := false @@ -1119,6 +1128,19 @@ func resourceWindowsVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interfa update.OsProfile.AllowExtensionOperations = utils.Bool(allowExtensionOperations) } + if d.HasChange("vm_agent_platform_updates_enabled") { + shouldUpdate = true + if update.OsProfile == nil { + update.OsProfile = &compute.OSProfile{} + } + + if update.OsProfile.WindowsConfiguration == nil { + update.OsProfile.WindowsConfiguration = &compute.WindowsConfiguration{} + } + + update.OsProfile.WindowsConfiguration.EnableVMAgentPlatformUpdates = utils.Bool(d.Get("vm_agent_platform_updates_enabled").(bool)) + } + if d.HasChange("patch_mode") { shouldUpdate = true diff --git a/internal/services/compute/windows_virtual_machine_resource_other_test.go b/internal/services/compute/windows_virtual_machine_resource_other_test.go index d5370d06b644..771b1a1d132f 100644 --- a/internal/services/compute/windows_virtual_machine_resource_other_test.go +++ b/internal/services/compute/windows_virtual_machine_resource_other_test.go @@ -86,6 +86,30 @@ func TestAccWindowsVirtualMachine_otherPatchModeUpdate(t *testing.T) { }) } +func TestAccWindowsVirtualMachine_otherVmAgentPlatformUpdates(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_windows_virtual_machine", "test") + r := WindowsVirtualMachineResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.otherVmAgentPlatformUpdatesEnabled(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("vm_agent_platform_updates_enabled").HasValue("true"), + ), + }, + data.ImportStep("admin_password"), + { + Config: r.otherVmAgentPlatformUpdatesDisabled(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("vm_agent_platform_updates_enabled").HasValue("false"), + ), + }, + data.ImportStep("admin_password"), + }) +} + func TestAccWindowsVirtualMachine_otherPatchAssessmentModeDefault(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_windows_virtual_machine", "test") r := WindowsVirtualMachineResource{} @@ -1222,7 +1246,7 @@ resource "azurerm_windows_virtual_machine" "test" { `, r.template(data), patchMode) } -func (r WindowsVirtualMachineResource) otherPatchModeManual(data acceptance.TestData) string { +func (r WindowsVirtualMachineResource) otherVmAgentPlatformUpdatesEnabled(data acceptance.TestData) string { return fmt.Sprintf(` %s @@ -1250,8 +1274,40 @@ resource "azurerm_windows_virtual_machine" "test" { version = "latest" } - enable_automatic_updates = false - patch_mode = "Manual" + vm_agent_platform_updates_enabled = true +} +`, r.template(data)) +} + +func (r WindowsVirtualMachineResource) otherVmAgentPlatformUpdatesDisabled(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_windows_virtual_machine" "test" { + name = local.vm_name + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_F2" + admin_username = "adminuser" + admin_password = "P@$$w0rd1234!" + + network_interface_ids = [ + azurerm_network_interface.test.id, + ] + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2016-Datacenter" + version = "latest" + } + + vm_agent_platform_updates_enabled = false } `, r.template(data)) } @@ -1322,6 +1378,40 @@ resource "azurerm_windows_virtual_machine" "test" { `, r.template(data)) } +func (r WindowsVirtualMachineResource) otherPatchModeManual(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_windows_virtual_machine" "test" { + name = local.vm_name + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_F2" + admin_username = "adminuser" + admin_password = "P@$$w0rd1234!" + + network_interface_ids = [ + azurerm_network_interface.test.id, + ] + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2016-Datacenter" + version = "latest" + } + + enable_automatic_updates = false + patch_mode = "Manual" +} +`, r.template(data)) +} + func (r WindowsVirtualMachineResource) otherPatchAssessmentModeDefault(data acceptance.TestData) string { return fmt.Sprintf(` %s diff --git a/website/docs/r/linux_virtual_machine.html.markdown b/website/docs/r/linux_virtual_machine.html.markdown index 3019c2e06f93..2d23d1578c2f 100644 --- a/website/docs/r/linux_virtual_machine.html.markdown +++ b/website/docs/r/linux_virtual_machine.html.markdown @@ -208,6 +208,8 @@ The following arguments are supported: * `user_data` - (Optional) The Base64-Encoded User Data which should be used for this Virtual Machine. +* `vm_agent_platform_updates_enabled` - (Optional) Specifies whether VMAgent Platform Updates is enabled. Defaults to `false`. + * `vtpm_enabled` - (Optional) Specifies whether vTPM should be enabled on the virtual machine. Changing this forces a new resource to be created. * `virtual_machine_scale_set_id` - (Optional) Specifies the Orchestrated Virtual Machine Scale Set that this Virtual Machine should be created within. Changing this forces a new resource to be created. diff --git a/website/docs/r/windows_virtual_machine.html.markdown b/website/docs/r/windows_virtual_machine.html.markdown index 13834e16ac49..edd40f458729 100644 --- a/website/docs/r/windows_virtual_machine.html.markdown +++ b/website/docs/r/windows_virtual_machine.html.markdown @@ -209,6 +209,8 @@ The following arguments are supported: ~> **NOTE:** Orchestrated Virtual Machine Scale Sets can be provisioned using [the `azurerm_orchestrated_virtual_machine_scale_set` resource](/docs/providers/azurerm/r/orchestrated_virtual_machine_scale_set.html). +* `vm_agent_platform_updates_enabled` - (Optional) Specifies whether VMAgent Platform Updates is enabled. Defaults to `false`. + * `vtpm_enabled` - (Optional) Specifies if vTPM (virtual Trusted Platform Module) and Trusted Launch is enabled for the Virtual Machine. Changing this forces a new resource to be created. * `winrm_listener` - (Optional) One or more `winrm_listener` blocks as defined below. Changing this forces a new resource to be created. From 39e764dbc417c828f1cc011525cbcd63149482e7 Mon Sep 17 00:00:00 2001 From: Zhenhua Hu Date: Fri, 15 Sep 2023 08:11:14 +0800 Subject: [PATCH 04/10] support `os_image_notification` --- .../compute/linux_virtual_machine_resource.go | 41 ++++++++- ...nux_virtual_machine_resource_other_test.go | 76 ++++++++++++++++ internal/services/compute/virtual_machine.go | 87 ++++++++++++++++--- .../windows_virtual_machine_resource.go | 41 ++++++++- ...ows_virtual_machine_resource_other_test.go | 72 +++++++++++++++ .../r/linux_virtual_machine.html.markdown | 10 +++ .../r/windows_virtual_machine.html.markdown | 10 +++ 7 files changed, 315 insertions(+), 22 deletions(-) diff --git a/internal/services/compute/linux_virtual_machine_resource.go b/internal/services/compute/linux_virtual_machine_resource.go index 2969d6b34aeb..b06922298ccf 100644 --- a/internal/services/compute/linux_virtual_machine_resource.go +++ b/internal/services/compute/linux_virtual_machine_resource.go @@ -363,6 +363,8 @@ func resourceLinuxVirtualMachine() *pluginsdk.Resource { "tags": tags.Schema(), + "os_image_notification": virtualMachineOsImageNotificationSchema(), + "termination_notification": virtualMachineTerminationNotificationSchema(), "user_data": { @@ -642,8 +644,22 @@ func resourceLinuxVirtualMachineCreate(d *pluginsdk.ResourceData, meta interface } } + var osImageNotificationProfile *compute.OSImageNotificationProfile + var terminateNotificationProfile *compute.TerminateNotificationProfile + + if v, ok := d.GetOk("os_image_notification"); ok { + osImageNotificationProfile = expandOsImageNotificationProfile(v.([]interface{})) + } + if v, ok := d.GetOk("termination_notification"); ok { - params.VirtualMachineProperties.ScheduledEventsProfile = expandVirtualMachineScheduledEventsProfile(v.([]interface{})) + terminateNotificationProfile = expandTerminateNotificationProfile(v.([]interface{})) + } + + if terminateNotificationProfile != nil || osImageNotificationProfile != nil { + params.VirtualMachineProperties.ScheduledEventsProfile = &compute.ScheduledEventsProfile{ + OsImageNotificationProfile: osImageNotificationProfile, + TerminateNotificationProfile: terminateNotificationProfile, + } } if !provisionVMAgent && allowExtensionOperations { @@ -960,7 +976,11 @@ func resourceLinuxVirtualMachineRead(d *pluginsdk.ResourceData, meta interface{} } if scheduleProfile := props.ScheduledEventsProfile; scheduleProfile != nil { - if err := d.Set("termination_notification", flattenVirtualMachineScheduledEventsProfile(scheduleProfile)); err != nil { + if err := d.Set("os_image_notification", flattenOsImageNotificationProfile(scheduleProfile.OsImageNotificationProfile)); err != nil { + return fmt.Errorf("setting `termination_notification`: %+v", err) + } + + if err := d.Set("termination_notification", flattenTerminateNotificationProfile(scheduleProfile.TerminateNotificationProfile)); err != nil { return fmt.Errorf("setting `termination_notification`: %+v", err) } } @@ -1391,11 +1411,24 @@ func resourceLinuxVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interface update.OsProfile.AllowExtensionOperations = utils.Bool(allowExtensionOperations) } + var osImageNotificationProfile *compute.OSImageNotificationProfile + var terminateNotificationProfile *compute.TerminateNotificationProfile + + if d.HasChange("os_image_notification") { + shouldUpdate = true + osImageNotificationProfile = expandOsImageNotificationProfile(d.Get("os_image_notification").([]interface{})) + } + if d.HasChange("termination_notification") { shouldUpdate = true + terminateNotificationProfile = expandTerminateNotificationProfile(d.Get("termination_notification").([]interface{})) + } - notificationRaw := d.Get("termination_notification").([]interface{}) - update.ScheduledEventsProfile = expandVirtualMachineScheduledEventsProfile(notificationRaw) + if osImageNotificationProfile != nil || terminateNotificationProfile != nil { + update.ScheduledEventsProfile = &compute.ScheduledEventsProfile{ + OsImageNotificationProfile: osImageNotificationProfile, + TerminateNotificationProfile: terminateNotificationProfile, + } } if d.HasChange("tags") { diff --git a/internal/services/compute/linux_virtual_machine_resource_other_test.go b/internal/services/compute/linux_virtual_machine_resource_other_test.go index 422b353208fc..13897635be33 100644 --- a/internal/services/compute/linux_virtual_machine_resource_other_test.go +++ b/internal/services/compute/linux_virtual_machine_resource_other_test.go @@ -532,6 +532,44 @@ func TestAccLinuxVirtualMachine_otherTags(t *testing.T) { }) } +func TestAccLinuxVirtualMachine_otherOsImageNotification(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine", "test") + r := LinuxVirtualMachineResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + // turn termination notification on + { + Config: r.otherOsImageNotification(data, true), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"), + check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("true"), + ), + }, + data.ImportStep("admin_password"), + // turn termination notification off + { + Config: r.otherOsImageNotification(data, false), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"), + check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("false"), + ), + }, + data.ImportStep("admin_password"), + // turn termination notification on again + { + Config: r.otherOsImageNotification(data, true), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"), + check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("true"), + ), + }, + data.ImportStep("admin_password"), + }) +} + func TestAccLinuxVirtualMachine_otherTerminationNotification(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine", "test") r := LinuxVirtualMachineResource{} @@ -2466,6 +2504,44 @@ resource "azurerm_linux_virtual_machine" "test" { `, r.template(data), data.RandomInteger) } +func (r LinuxVirtualMachineResource) otherOsImageNotification(data acceptance.TestData, enabled bool) string { + return fmt.Sprintf(` +%s + +resource "azurerm_linux_virtual_machine" "test" { + name = "acctestVM-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_F2" + admin_username = "adminuser" + network_interface_ids = [ + azurerm_network_interface.test.id, + ] + + admin_ssh_key { + username = "adminuser" + public_key = local.first_public_key + } + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } + + os_image_notification { + enabled = %t + } +} +`, r.template(data), data.RandomInteger, enabled) +} + func (r LinuxVirtualMachineResource) otherTerminationNotification(data acceptance.TestData, enabled bool) string { return fmt.Sprintf(` %s diff --git a/internal/services/compute/virtual_machine.go b/internal/services/compute/virtual_machine.go index 8dea20a960bb..b4c74f766502 100644 --- a/internal/services/compute/virtual_machine.go +++ b/internal/services/compute/virtual_machine.go @@ -425,6 +425,30 @@ func flattenVirtualMachineOSDisk(ctx context.Context, disksClient *disks.DisksCl }, nil } +func virtualMachineOsImageNotificationSchema() *pluginsdk.Schema { + return &pluginsdk.Schema{ + Type: pluginsdk.TypeList, + Optional: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "enabled": { + Type: pluginsdk.TypeBool, + Required: true, + }, + "timeout": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + "PT15M", + }, false), + Default: "PT15M", + }, + }, + }, + } +} + func virtualMachineTerminationNotificationSchema() *pluginsdk.Schema { return &pluginsdk.Schema{ Type: pluginsdk.TypeList, @@ -448,12 +472,27 @@ func virtualMachineTerminationNotificationSchema() *pluginsdk.Schema { } } -func expandVirtualMachineScheduledEventsProfile(input []interface{}) *compute.ScheduledEventsProfile { +func expandOsImageNotificationProfile(input []interface{}) *compute.OSImageNotificationProfile { if len(input) == 0 { - return &compute.ScheduledEventsProfile{ - TerminateNotificationProfile: &compute.TerminateNotificationProfile{ - Enable: utils.Bool(false), - }, + return &compute.OSImageNotificationProfile{ + Enable: utils.Bool(false), + } + } + + raw := input[0].(map[string]interface{}) + enabled := raw["enabled"].(bool) + timeout := raw["timeout"].(string) + + return &compute.OSImageNotificationProfile{ + Enable: &enabled, + NotBeforeTimeout: &timeout, + } +} + +func expandTerminateNotificationProfile(input []interface{}) *compute.TerminateNotificationProfile { + if len(input) == 0 { + return &compute.TerminateNotificationProfile{ + Enable: utils.Bool(false), } } @@ -461,26 +500,46 @@ func expandVirtualMachineScheduledEventsProfile(input []interface{}) *compute.Sc enabled := raw["enabled"].(bool) timeout := raw["timeout"].(string) - return &compute.ScheduledEventsProfile{ - TerminateNotificationProfile: &compute.TerminateNotificationProfile{ - Enable: &enabled, - NotBeforeTimeout: &timeout, + return &compute.TerminateNotificationProfile{ + Enable: &enabled, + NotBeforeTimeout: &timeout, + } +} + +func flattenOsImageNotificationProfile(input *compute.OSImageNotificationProfile) []interface{} { + // if enabled is set to false, there will be no ScheduledEventsProfile in response, to avoid plan non empty when + // a user explicitly set enabled to false, we need to assign a default block to this field + + enabled := false + if input != nil && input.Enable != nil { + enabled = *input.Enable + } + + timeout := "PT15M" + if input != nil && input.NotBeforeTimeout != nil { + timeout = *input.NotBeforeTimeout + } + + return []interface{}{ + map[string]interface{}{ + "enabled": enabled, + "timeout": timeout, }, } } -func flattenVirtualMachineScheduledEventsProfile(input *compute.ScheduledEventsProfile) []interface{} { +func flattenTerminateNotificationProfile(input *compute.TerminateNotificationProfile) []interface{} { // if enabled is set to false, there will be no ScheduledEventsProfile in response, to avoid plan non empty when // a user explicitly set enabled to false, we need to assign a default block to this field enabled := false - if input != nil && input.TerminateNotificationProfile != nil && input.TerminateNotificationProfile.Enable != nil { - enabled = *input.TerminateNotificationProfile.Enable + if input != nil && input.Enable != nil { + enabled = *input.Enable } timeout := "PT5M" - if input != nil && input.TerminateNotificationProfile != nil && input.TerminateNotificationProfile.NotBeforeTimeout != nil { - timeout = *input.TerminateNotificationProfile.NotBeforeTimeout + if input != nil && input.NotBeforeTimeout != nil { + timeout = *input.NotBeforeTimeout } return []interface{}{ diff --git a/internal/services/compute/windows_virtual_machine_resource.go b/internal/services/compute/windows_virtual_machine_resource.go index 4bcd31a67db2..19135c39e1d9 100644 --- a/internal/services/compute/windows_virtual_machine_resource.go +++ b/internal/services/compute/windows_virtual_machine_resource.go @@ -350,6 +350,8 @@ func resourceWindowsVirtualMachine() *pluginsdk.Resource { "tags": tags.Schema(), + "os_image_notification": virtualMachineOsImageNotificationSchema(), + "termination_notification": virtualMachineTerminationNotificationSchema(), "timezone": { @@ -766,8 +768,22 @@ func resourceWindowsVirtualMachineCreate(d *pluginsdk.ResourceData, meta interfa params.PlatformFaultDomain = utils.Int32(int32(platformFaultDomain)) } + var osImageNotificationProfile *compute.OSImageNotificationProfile + var terminateNotificationProfile *compute.TerminateNotificationProfile + + if v, ok := d.GetOk("os_image_notification"); ok { + osImageNotificationProfile = expandOsImageNotificationProfile(v.([]interface{})) + } + if v, ok := d.GetOk("termination_notification"); ok { - params.VirtualMachineProperties.ScheduledEventsProfile = expandVirtualMachineScheduledEventsProfile(v.([]interface{})) + terminateNotificationProfile = expandTerminateNotificationProfile(v.([]interface{})) + } + + if terminateNotificationProfile != nil || osImageNotificationProfile != nil { + params.VirtualMachineProperties.ScheduledEventsProfile = &compute.ScheduledEventsProfile{ + OsImageNotificationProfile: osImageNotificationProfile, + TerminateNotificationProfile: terminateNotificationProfile, + } } if v, ok := d.GetOk("timezone"); ok { @@ -1001,7 +1017,11 @@ func resourceWindowsVirtualMachineRead(d *pluginsdk.ResourceData, meta interface } if scheduleProfile := props.ScheduledEventsProfile; scheduleProfile != nil { - if err := d.Set("termination_notification", flattenVirtualMachineScheduledEventsProfile(scheduleProfile)); err != nil { + if err := d.Set("os_image_notification", flattenOsImageNotificationProfile(scheduleProfile.OsImageNotificationProfile)); err != nil { + return fmt.Errorf("setting `termination_notification`: %+v", err) + } + + if err := d.Set("termination_notification", flattenTerminateNotificationProfile(scheduleProfile.TerminateNotificationProfile)); err != nil { return fmt.Errorf("setting `termination_notification`: %+v", err) } } @@ -1446,11 +1466,24 @@ func resourceWindowsVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interfa update.Tags = tags.Expand(tagsRaw) } + var osImageNotificationProfile *compute.OSImageNotificationProfile + var terminateNotificationProfile *compute.TerminateNotificationProfile + + if d.HasChange("os_image_notification") { + shouldUpdate = true + osImageNotificationProfile = expandOsImageNotificationProfile(d.Get("os_image_notification").([]interface{})) + } + if d.HasChange("termination_notification") { shouldUpdate = true + terminateNotificationProfile = expandTerminateNotificationProfile(d.Get("termination_notification").([]interface{})) + } - notificationRaw := d.Get("termination_notification").([]interface{}) - update.ScheduledEventsProfile = expandVirtualMachineScheduledEventsProfile(notificationRaw) + if osImageNotificationProfile != nil || terminateNotificationProfile != nil { + update.ScheduledEventsProfile = &compute.ScheduledEventsProfile{ + OsImageNotificationProfile: osImageNotificationProfile, + TerminateNotificationProfile: terminateNotificationProfile, + } } if d.HasChange("additional_capabilities") { diff --git a/internal/services/compute/windows_virtual_machine_resource_other_test.go b/internal/services/compute/windows_virtual_machine_resource_other_test.go index 771b1a1d132f..f9d4eae52a35 100644 --- a/internal/services/compute/windows_virtual_machine_resource_other_test.go +++ b/internal/services/compute/windows_virtual_machine_resource_other_test.go @@ -738,6 +738,44 @@ func TestAccWindowsVirtualMachine_otherTags(t *testing.T) { }) } +func TestAccWindowsVirtualMachine_otherOsImageNotification(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_windows_virtual_machine", "test") + r := WindowsVirtualMachineResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + // turn termination notification on + { + Config: r.otherOsImageNotification(data, true), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"), + check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("true"), + ), + }, + data.ImportStep("admin_password"), + // turn termination notification off + { + Config: r.otherOsImageNotification(data, false), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"), + check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("false"), + ), + }, + data.ImportStep("admin_password"), + // turn termination notification on again + { + Config: r.otherOsImageNotification(data, true), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"), + check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("true"), + ), + }, + data.ImportStep("admin_password"), + }) +} + func TestAccWindowsVirtualMachine_otherTerminationNotification(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_windows_virtual_machine", "test") r := WindowsVirtualMachineResource{} @@ -2844,6 +2882,40 @@ resource "azurerm_windows_virtual_machine" "test" { `, r.template(data)) } +func (r WindowsVirtualMachineResource) otherOsImageNotification(data acceptance.TestData, enabled bool) string { + return fmt.Sprintf(` +%s + +resource "azurerm_windows_virtual_machine" "test" { + name = local.vm_name + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_F2" + admin_username = "adminuser" + admin_password = "P@$$w0rd1234!" + network_interface_ids = [ + azurerm_network_interface.test.id, + ] + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2016-Datacenter" + version = "latest" + } + + os_image_notification { + enabled = %t + } +} +`, r.template(data), enabled) +} + func (r WindowsVirtualMachineResource) otherTerminationNotification(data acceptance.TestData, enabled bool) string { return fmt.Sprintf(` %s diff --git a/website/docs/r/linux_virtual_machine.html.markdown b/website/docs/r/linux_virtual_machine.html.markdown index 2d23d1578c2f..44a4318ef806 100644 --- a/website/docs/r/linux_virtual_machine.html.markdown +++ b/website/docs/r/linux_virtual_machine.html.markdown @@ -204,6 +204,8 @@ The following arguments are supported: * `tags` - (Optional) A mapping of tags which should be assigned to this Virtual Machine. +* `os_image_notification` - (Optional) A `os_image_notification` block as defined below. + * `termination_notification` - (Optional) A `termination_notification` block as defined below. * `user_data` - (Optional) The Base64-Encoded User Data which should be used for this Virtual Machine. @@ -352,6 +354,14 @@ The `source_image_reference` block supports the following: --- +A `os_image_notification` block supports the following: + +* `enabled` - (Required) Should the OS image notification be enabled on this Virtual Machine? + +* `timeout` - (Optional) Length of time a notification to be sent to the VM on the instance metadata server till the VM gets OS upgraded. The only possible value is `PT15M`. Defaults to `PT15M`. + +--- + A `termination_notification` block supports the following: * `enabled` - (Required) Should the termination notification be enabled on this Virtual Machine? diff --git a/website/docs/r/windows_virtual_machine.html.markdown b/website/docs/r/windows_virtual_machine.html.markdown index edd40f458729..f0d9b6fdbb72 100644 --- a/website/docs/r/windows_virtual_machine.html.markdown +++ b/website/docs/r/windows_virtual_machine.html.markdown @@ -199,6 +199,8 @@ The following arguments are supported: * `tags` - (Optional) A mapping of tags which should be assigned to this Virtual Machine. +* `os_image_notification` - (Optional) A `os_image_notification` block as defined below. + * `termination_notification` - (Optional) A `termination_notification` block as defined below. * `timezone` - (Optional) Specifies the Time Zone which should be used by the Virtual Machine, [the possible values are defined here](https://jackstromberg.com/2017/01/list-of-time-zones-consumed-by-azure/). Changing this forces a new resource to be created. @@ -353,6 +355,14 @@ The `source_image_reference` block supports the following: --- +A `os_image_notification` block supports the following: + +* `enabled` - (Required) Should the OS image notification be enabled on this Virtual Machine? + +* `timeout` - (Optional) Length of time a notification to be sent to the VM on the instance metadata server till the VM gets OS upgraded. The only possible value is `PT15M`. Defaults to `PT15M`. + +--- + A `termination_notification` block supports the following: * `enabled` - (Required) Should the termination notification be enabled on this Virtual Machine? From d8727f528606533e050946eb78a53cbe2eea28a5 Mon Sep 17 00:00:00 2001 From: Zhenhua Hu Date: Wed, 27 Sep 2023 10:19:25 +0800 Subject: [PATCH 05/10] support `disk_controller_type` --- .../compute/linux_virtual_machine_resource.go | 45 +++++++- ...x_virtual_machine_resource_disk_os_test.go | 106 ++++++++++++++++++ .../windows_virtual_machine_resource.go | 45 +++++++- ...s_virtual_machine_resource_disk_os_test.go | 98 ++++++++++++++++ .../r/linux_virtual_machine.html.markdown | 4 + .../r/windows_virtual_machine.html.markdown | 4 + 6 files changed, 296 insertions(+), 6 deletions(-) diff --git a/internal/services/compute/linux_virtual_machine_resource.go b/internal/services/compute/linux_virtual_machine_resource.go index b06922298ccf..7009b159073f 100644 --- a/internal/services/compute/linux_virtual_machine_resource.go +++ b/internal/services/compute/linux_virtual_machine_resource.go @@ -24,6 +24,7 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" azValidate "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/features" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse" computeValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate" @@ -39,7 +40,7 @@ import ( ) func resourceLinuxVirtualMachine() *pluginsdk.Resource { - return &pluginsdk.Resource{ + resource := &pluginsdk.Resource{ Create: resourceLinuxVirtualMachineCreate, Read: resourceLinuxVirtualMachineRead, Update: resourceLinuxVirtualMachineUpdate, @@ -404,6 +405,19 @@ func resourceLinuxVirtualMachine() *pluginsdk.Resource { }, }, } + + if features.FourPointOhBeta() { + resource.Schema["disk_controller_type"] = &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + string(compute.DiskControllerTypesNVMe), + string(compute.DiskControllerTypesSCSI), + }, false), + } + } + + return resource } func resourceLinuxVirtualMachineCreate(d *pluginsdk.ResourceData, meta interface{}) error { @@ -530,6 +544,12 @@ func resourceLinuxVirtualMachineCreate(d *pluginsdk.ResourceData, meta interface Tags: tags.Expand(t), } + if features.FourPointOhBeta() { + if diskControllerType, ok := d.GetOk("disk_controller_type"); ok { + params.StorageProfile.DiskControllerType = compute.DiskControllerTypes(diskControllerType.(string)) + } + } + if encryptionAtHostEnabled, ok := d.GetOk("encryption_at_host_enabled"); ok { if encryptionAtHostEnabled.(bool) { if compute.SecurityEncryptionTypesDiskWithVMGuestState == compute.SecurityEncryptionTypes(securityEncryptionType) { @@ -948,6 +968,10 @@ func resourceLinuxVirtualMachineRead(d *pluginsdk.ResourceData, meta interface{} d.Set("proximity_placement_group_id", proximityPlacementGroupId) if profile := props.StorageProfile; profile != nil { + if features.FourPointOhBeta() { + d.Set("disk_controller_type", string(props.StorageProfile.DiskControllerType)) + } + // the storage_account_type isn't returned so we need to look it up flattenedOSDisk, err := flattenVirtualMachineOSDisk(ctx, disksClient, profile.OsDisk) if err != nil { @@ -1208,6 +1232,19 @@ func resourceLinuxVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interface } } + if features.FourPointOhBeta() { + if d.HasChange("disk_controller_type") { + shouldUpdate = true + shouldDeallocate = true + + if update.VirtualMachineProperties.StorageProfile == nil { + update.VirtualMachineProperties.StorageProfile = &compute.StorageProfile{} + } + + update.VirtualMachineProperties.StorageProfile.DiskControllerType = compute.DiskControllerTypes(d.Get("disk_controller_type").(string)) + } + } + if d.HasChange("os_disk") { shouldUpdate = true @@ -1221,9 +1258,11 @@ func resourceLinuxVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interface return fmt.Errorf("expanding `os_disk`: %+v", err) } - update.VirtualMachineProperties.StorageProfile = &compute.StorageProfile{ - OsDisk: osDisk, + if update.VirtualMachineProperties.StorageProfile == nil { + update.VirtualMachineProperties.StorageProfile = &compute.StorageProfile{} } + + update.VirtualMachineProperties.StorageProfile.OsDisk = osDisk } if d.HasChange("proximity_placement_group_id") { diff --git a/internal/services/compute/linux_virtual_machine_resource_disk_os_test.go b/internal/services/compute/linux_virtual_machine_resource_disk_os_test.go index 3dcdd4550ac9..179d1603f9ef 100644 --- a/internal/services/compute/linux_virtual_machine_resource_disk_os_test.go +++ b/internal/services/compute/linux_virtual_machine_resource_disk_os_test.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/features" ) func TestAccLinuxVirtualMachine_diskOSBasic(t *testing.T) { @@ -300,6 +301,39 @@ func TestAccLinuxVirtualMachine_diskOSStorageTypeUpdate(t *testing.T) { }) } +func TestAccLinuxVirtualMachine_diskOSControllerType(t *testing.T) { + if !features.FourPointOhBeta() { + t.Skipf("Test applies after 4.0 only") + } + + data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine", "test") + r := LinuxVirtualMachineResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.diskOSControllerTypeNVMe(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.diskOSControllerTypeSCSI(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.diskOSControllerTypeNVMe(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + func TestAccLinuxVirtualMachine_diskOSWriteAcceleratorEnabled(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine", "test") r := LinuxVirtualMachineResource{} @@ -892,6 +926,78 @@ func (r LinuxVirtualMachineResource) diskOSStorageAccountTypeWithRestrictedLocat return r.diskOSStorageAccountType(data, accountType) } +func (r LinuxVirtualMachineResource) diskOSControllerTypeSCSI(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_linux_virtual_machine" "test" { + name = "acctestVM-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_B1s" + admin_username = "adminuser" + disk_controller_type = "SCSI" + + network_interface_ids = [ + azurerm_network_interface.test.id, + ] + + admin_ssh_key { + username = "adminuser" + public_key = local.first_public_key + } + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "Canonical" + offer = "0001-com-ubuntu-server-focal" + sku = "20_04-lts-gen2" + version = "latest" + } +} +`, r.template(data), data.RandomInteger) +} + +func (r LinuxVirtualMachineResource) diskOSControllerTypeNVMe(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_linux_virtual_machine" "test" { + name = "acctestVM-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_E2bds_v5" + admin_username = "adminuser" + disk_controller_type = "NVMe" + + network_interface_ids = [ + azurerm_network_interface.test.id, + ] + + admin_ssh_key { + username = "adminuser" + public_key = local.first_public_key + } + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "Canonical" + offer = "0001-com-ubuntu-server-focal" + sku = "20_04-lts-gen2" + version = "latest" + } +} +`, r.template(data), data.RandomInteger) +} + func (r LinuxVirtualMachineResource) diskOSWriteAcceleratorEnabled(data acceptance.TestData, enabled bool) string { return fmt.Sprintf(` %s diff --git a/internal/services/compute/windows_virtual_machine_resource.go b/internal/services/compute/windows_virtual_machine_resource.go index 19135c39e1d9..d559b44cf209 100644 --- a/internal/services/compute/windows_virtual_machine_resource.go +++ b/internal/services/compute/windows_virtual_machine_resource.go @@ -25,6 +25,7 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" azValidate "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/features" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse" computeValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate" @@ -40,7 +41,7 @@ import ( ) func resourceWindowsVirtualMachine() *pluginsdk.Resource { - return &pluginsdk.Resource{ + resource := &pluginsdk.Resource{ Create: resourceWindowsVirtualMachineCreate, Read: resourceWindowsVirtualMachineRead, Update: resourceWindowsVirtualMachineUpdate, @@ -431,6 +432,19 @@ func resourceWindowsVirtualMachine() *pluginsdk.Resource { }, }, } + + if features.FourPointOhBeta() { + resource.Schema["disk_controller_type"] = &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + string(compute.DiskControllerTypesNVMe), + string(compute.DiskControllerTypesSCSI), + }, false), + } + } + + return resource } func resourceWindowsVirtualMachineCreate(d *pluginsdk.ResourceData, meta interface{}) error { @@ -566,6 +580,12 @@ func resourceWindowsVirtualMachineCreate(d *pluginsdk.ResourceData, meta interfa Tags: tags.Expand(t), } + if features.FourPointOhBeta() { + if diskControllerType, ok := d.GetOk("disk_controller_type"); ok { + params.StorageProfile.DiskControllerType = compute.DiskControllerTypes(diskControllerType.(string)) + } + } + if !provisionVMAgent && allowExtensionOperations { return fmt.Errorf("`allow_extension_operations` cannot be set to `true` when `provision_vm_agent` is set to `false`") } @@ -990,6 +1010,10 @@ func resourceWindowsVirtualMachineRead(d *pluginsdk.ResourceData, meta interface d.Set("proximity_placement_group_id", proximityPlacementGroupId) if profile := props.StorageProfile; profile != nil { + if features.FourPointOhBeta() { + d.Set("disk_controller_type", string(props.StorageProfile.DiskControllerType)) + } + // the storage_account_type isn't returned so we need to look it up flattenedOSDisk, err := flattenVirtualMachineOSDisk(ctx, disksClient, profile.OsDisk) if err != nil { @@ -1382,6 +1406,19 @@ func resourceWindowsVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interfa } } + if features.FourPointOhBeta() { + if d.HasChange("disk_controller_type") { + shouldUpdate = true + shouldDeallocate = true + + if update.VirtualMachineProperties.StorageProfile == nil { + update.VirtualMachineProperties.StorageProfile = &compute.StorageProfile{} + } + + update.VirtualMachineProperties.StorageProfile.DiskControllerType = compute.DiskControllerTypes(d.Get("disk_controller_type").(string)) + } + } + if d.HasChange("os_disk") { shouldUpdate = true @@ -1395,9 +1432,11 @@ func resourceWindowsVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interfa return fmt.Errorf("expanding `os_disk`: %+v", err) } - update.VirtualMachineProperties.StorageProfile = &compute.StorageProfile{ - OsDisk: osDisk, + if update.VirtualMachineProperties.StorageProfile == nil { + update.VirtualMachineProperties.StorageProfile = &compute.StorageProfile{} } + + update.VirtualMachineProperties.StorageProfile.OsDisk = osDisk } if d.HasChange("proximity_placement_group_id") { diff --git a/internal/services/compute/windows_virtual_machine_resource_disk_os_test.go b/internal/services/compute/windows_virtual_machine_resource_disk_os_test.go index 3313a410a927..86c2329ea892 100644 --- a/internal/services/compute/windows_virtual_machine_resource_disk_os_test.go +++ b/internal/services/compute/windows_virtual_machine_resource_disk_os_test.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/features" ) func TestAccWindowsVirtualMachine_diskOSBasic(t *testing.T) { @@ -300,6 +301,39 @@ func TestAccWindowsVirtualMachine_diskOSStorageTypeUpdate(t *testing.T) { }) } +func TestAccWindowsVirtualMachine_diskOSControllerType(t *testing.T) { + if !features.FourPointOhBeta() { + t.Skipf("Test applies after 4.0 only") + } + + data := acceptance.BuildTestData(t, "azurerm_windows_virtual_machine", "test") + r := WindowsVirtualMachineResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.diskOSControllerTypeNVMe(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep("admin_password"), + { + Config: r.diskOSControllerTypeSCSI(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep("admin_password"), + { + Config: r.diskOSControllerTypeNVMe(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep("admin_password"), + }) +} + func TestAccWindowsVirtualMachine_diskOSWriteAcceleratorEnabled(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_windows_virtual_machine", "test") r := WindowsVirtualMachineResource{} @@ -853,6 +887,70 @@ func (r WindowsVirtualMachineResource) diskOSStorageAccountTypeWithRestrictedLoc return r.diskOSStorageAccountType(data, accountType) } +func (r WindowsVirtualMachineResource) diskOSControllerTypeSCSI(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_windows_virtual_machine" "test" { + name = local.vm_name + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_E2bds_v5" + admin_username = "adminuser" + admin_password = "P@$$w0rd1234!" + disk_controller_type = "SCSI" + + network_interface_ids = [ + azurerm_network_interface.test.id, + ] + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "microsoftwindowsserver" + offer = "windowsserver" + sku = "2022-datacenter-azure-edition" + version = "latest" + } +} +`, r.template(data)) +} + +func (r WindowsVirtualMachineResource) diskOSControllerTypeNVMe(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_windows_virtual_machine" "test" { + name = local.vm_name + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_E2bds_v5" + admin_username = "adminuser" + admin_password = "P@$$w0rd1234!" + disk_controller_type = "NVMe" + + network_interface_ids = [ + azurerm_network_interface.test.id, + ] + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "microsoftwindowsserver" + offer = "windowsserver" + sku = "2022-datacenter-azure-edition" + version = "latest" + } +} +`, r.template(data)) +} + func (r WindowsVirtualMachineResource) diskOSWriteAcceleratorEnabled(data acceptance.TestData, enabled bool) string { return fmt.Sprintf(` %s diff --git a/website/docs/r/linux_virtual_machine.html.markdown b/website/docs/r/linux_virtual_machine.html.markdown index 44a4318ef806..9d58c2f09501 100644 --- a/website/docs/r/linux_virtual_machine.html.markdown +++ b/website/docs/r/linux_virtual_machine.html.markdown @@ -148,6 +148,10 @@ The following arguments are supported: -> **NOTE:** When an `admin_password` is specified `disable_password_authentication` must be set to `false`. +* `disk_controller_type` - (Optional) Specifies the Disk Controller Type used for this Virtual Machine. Possible values are `SCSI` and `NVMe`. + +-> **Note:** This will be available only from the next major version of the Azure Provider (4.0). + * `edge_zone` - (Optional) Specifies the Edge Zone within the Azure Region where this Linux Virtual Machine should exist. Changing this forces a new Linux Virtual Machine to be created. * `encryption_at_host_enabled` - (Optional) Should all of the disks (including the temp disk) attached to this Virtual Machine be encrypted by enabling Encryption at Host? diff --git a/website/docs/r/windows_virtual_machine.html.markdown b/website/docs/r/windows_virtual_machine.html.markdown index f0d9b6fdbb72..83ad257a1f82 100644 --- a/website/docs/r/windows_virtual_machine.html.markdown +++ b/website/docs/r/windows_virtual_machine.html.markdown @@ -137,6 +137,10 @@ The following arguments are supported: * `edge_zone` - (Optional) Specifies the Edge Zone within the Azure Region where this Windows Virtual Machine should exist. Changing this forces a new Windows Virtual Machine to be created. +* `disk_controller_type` - (Optional) Specifies the Disk Controller Type used for this Virtual Machine. Possible values are `SCSI` and `NVMe`. + +-> **Note:** This will be available only from the next major version of the Azure Provider (4.0). + * `enable_automatic_updates` - (Optional) Specifies if Automatic Updates are Enabled for the Windows Virtual Machine. Changing this forces a new resource to be created. Defaults to `true`. * `encryption_at_host_enabled` - (Optional) Should all of the disks (including the temp disk) attached to this Virtual Machine be encrypted by enabling Encryption at Host? From 0bc192ce2b4b53aace54e17342e1f1e3a6faf8b6 Mon Sep 17 00:00:00 2001 From: Zhenhua Hu Date: Wed, 27 Sep 2023 16:16:49 +0800 Subject: [PATCH 06/10] fix lint --- ...x_virtual_machine_resource_disk_os_test.go | 28 +++++++++---------- ...nux_virtual_machine_resource_other_test.go | 12 ++++---- ...s_virtual_machine_resource_disk_os_test.go | 24 ++++++++-------- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/internal/services/compute/linux_virtual_machine_resource_disk_os_test.go b/internal/services/compute/linux_virtual_machine_resource_disk_os_test.go index 179d1603f9ef..d6150adff12e 100644 --- a/internal/services/compute/linux_virtual_machine_resource_disk_os_test.go +++ b/internal/services/compute/linux_virtual_machine_resource_disk_os_test.go @@ -931,11 +931,11 @@ func (r LinuxVirtualMachineResource) diskOSControllerTypeSCSI(data acceptance.Te %s resource "azurerm_linux_virtual_machine" "test" { - name = "acctestVM-%d" - resource_group_name = azurerm_resource_group.test.name - location = azurerm_resource_group.test.location - size = "Standard_B1s" - admin_username = "adminuser" + name = "acctestVM-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_B1s" + admin_username = "adminuser" disk_controller_type = "SCSI" network_interface_ids = [ @@ -954,8 +954,8 @@ resource "azurerm_linux_virtual_machine" "test" { source_image_reference { publisher = "Canonical" - offer = "0001-com-ubuntu-server-focal" - sku = "20_04-lts-gen2" + offer = "0001-com-ubuntu-server-jammy" + sku = "22_04-lts-gen2" version = "latest" } } @@ -967,11 +967,11 @@ func (r LinuxVirtualMachineResource) diskOSControllerTypeNVMe(data acceptance.Te %s resource "azurerm_linux_virtual_machine" "test" { - name = "acctestVM-%d" - resource_group_name = azurerm_resource_group.test.name - location = azurerm_resource_group.test.location - size = "Standard_E2bds_v5" - admin_username = "adminuser" + name = "acctestVM-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_E2bds_v5" + admin_username = "adminuser" disk_controller_type = "NVMe" network_interface_ids = [ @@ -990,8 +990,8 @@ resource "azurerm_linux_virtual_machine" "test" { source_image_reference { publisher = "Canonical" - offer = "0001-com-ubuntu-server-focal" - sku = "20_04-lts-gen2" + offer = "0001-com-ubuntu-server-jammy" + sku = "22_04-lts-gen2" version = "latest" } } diff --git a/internal/services/compute/linux_virtual_machine_resource_other_test.go b/internal/services/compute/linux_virtual_machine_resource_other_test.go index 13897635be33..cc49dcd697ae 100644 --- a/internal/services/compute/linux_virtual_machine_resource_other_test.go +++ b/internal/services/compute/linux_virtual_machine_resource_other_test.go @@ -1236,8 +1236,8 @@ resource "azurerm_linux_virtual_machine" "test" { source_image_reference { publisher = "Canonical" - offer = "UbuntuServer" - sku = "16.04-LTS" + offer = "0001-com-ubuntu-server-jammy" + sku = "22_04-lts" version = "latest" } } @@ -1270,8 +1270,8 @@ resource "azurerm_linux_virtual_machine" "test" { source_image_reference { publisher = "Canonical" - offer = "UbuntuServer" - sku = "16.04-LTS" + offer = "0001-com-ubuntu-server-jammy" + sku = "22_04-lts" version = "latest" } } @@ -2530,8 +2530,8 @@ resource "azurerm_linux_virtual_machine" "test" { source_image_reference { publisher = "Canonical" - offer = "UbuntuServer" - sku = "16.04-LTS" + offer = "0001-com-ubuntu-server-jammy" + sku = "22_04-lts" version = "latest" } diff --git a/internal/services/compute/windows_virtual_machine_resource_disk_os_test.go b/internal/services/compute/windows_virtual_machine_resource_disk_os_test.go index 86c2329ea892..d0d064986a16 100644 --- a/internal/services/compute/windows_virtual_machine_resource_disk_os_test.go +++ b/internal/services/compute/windows_virtual_machine_resource_disk_os_test.go @@ -892,12 +892,12 @@ func (r WindowsVirtualMachineResource) diskOSControllerTypeSCSI(data acceptance. %s resource "azurerm_windows_virtual_machine" "test" { - name = local.vm_name - resource_group_name = azurerm_resource_group.test.name - location = azurerm_resource_group.test.location - size = "Standard_E2bds_v5" - admin_username = "adminuser" - admin_password = "P@$$w0rd1234!" + name = local.vm_name + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_E2bds_v5" + admin_username = "adminuser" + admin_password = "P@$$w0rd1234!" disk_controller_type = "SCSI" network_interface_ids = [ @@ -924,12 +924,12 @@ func (r WindowsVirtualMachineResource) diskOSControllerTypeNVMe(data acceptance. %s resource "azurerm_windows_virtual_machine" "test" { - name = local.vm_name - resource_group_name = azurerm_resource_group.test.name - location = azurerm_resource_group.test.location - size = "Standard_E2bds_v5" - admin_username = "adminuser" - admin_password = "P@$$w0rd1234!" + name = local.vm_name + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_E2bds_v5" + admin_username = "adminuser" + admin_password = "P@$$w0rd1234!" disk_controller_type = "NVMe" network_interface_ids = [ From ad160f6a6a8158378920ae2a82683a432d60b22d Mon Sep 17 00:00:00 2001 From: Zhenhua Hu Date: Thu, 28 Sep 2023 14:16:16 +0800 Subject: [PATCH 07/10] bug fix --- .../services/compute/linux_virtual_machine_resource.go | 3 ++- .../compute/linux_virtual_machine_resource_other_test.go | 6 +++--- internal/services/compute/virtual_machine.go | 7 +++++-- .../services/compute/windows_virtual_machine_resource.go | 3 ++- .../compute/windows_virtual_machine_resource_other_test.go | 6 +++--- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/internal/services/compute/linux_virtual_machine_resource.go b/internal/services/compute/linux_virtual_machine_resource.go index 7009b159073f..fc5be3d8d5f0 100644 --- a/internal/services/compute/linux_virtual_machine_resource.go +++ b/internal/services/compute/linux_virtual_machine_resource.go @@ -1000,7 +1000,8 @@ func resourceLinuxVirtualMachineRead(d *pluginsdk.ResourceData, meta interface{} } if scheduleProfile := props.ScheduledEventsProfile; scheduleProfile != nil { - if err := d.Set("os_image_notification", flattenOsImageNotificationProfile(scheduleProfile.OsImageNotificationProfile)); err != nil { + _, isConfigured := d.GetOk("os_image_notification") + if err := d.Set("os_image_notification", flattenOsImageNotificationProfile(scheduleProfile.OsImageNotificationProfile, isConfigured)); err != nil { return fmt.Errorf("setting `termination_notification`: %+v", err) } diff --git a/internal/services/compute/linux_virtual_machine_resource_other_test.go b/internal/services/compute/linux_virtual_machine_resource_other_test.go index cc49dcd697ae..fe593ca45bdf 100644 --- a/internal/services/compute/linux_virtual_machine_resource_other_test.go +++ b/internal/services/compute/linux_virtual_machine_resource_other_test.go @@ -546,7 +546,7 @@ func TestAccLinuxVirtualMachine_otherOsImageNotification(t *testing.T) { check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("true"), ), }, - data.ImportStep("admin_password"), + data.ImportStep("os_image_notification"), // turn termination notification off { Config: r.otherOsImageNotification(data, false), @@ -556,7 +556,7 @@ func TestAccLinuxVirtualMachine_otherOsImageNotification(t *testing.T) { check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("false"), ), }, - data.ImportStep("admin_password"), + data.ImportStep("os_image_notification"), // turn termination notification on again { Config: r.otherOsImageNotification(data, true), @@ -566,7 +566,7 @@ func TestAccLinuxVirtualMachine_otherOsImageNotification(t *testing.T) { check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("true"), ), }, - data.ImportStep("admin_password"), + data.ImportStep("os_image_notification"), }) } diff --git a/internal/services/compute/virtual_machine.go b/internal/services/compute/virtual_machine.go index b4c74f766502..db8eaceb11b0 100644 --- a/internal/services/compute/virtual_machine.go +++ b/internal/services/compute/virtual_machine.go @@ -506,10 +506,13 @@ func expandTerminateNotificationProfile(input []interface{}) *compute.TerminateN } } -func flattenOsImageNotificationProfile(input *compute.OSImageNotificationProfile) []interface{} { +func flattenOsImageNotificationProfile(input *compute.OSImageNotificationProfile, isConfigured bool) []interface{} { + if input == nil && !isConfigured { + return nil + } + // if enabled is set to false, there will be no ScheduledEventsProfile in response, to avoid plan non empty when // a user explicitly set enabled to false, we need to assign a default block to this field - enabled := false if input != nil && input.Enable != nil { enabled = *input.Enable diff --git a/internal/services/compute/windows_virtual_machine_resource.go b/internal/services/compute/windows_virtual_machine_resource.go index d559b44cf209..3fba2eb1f4e0 100644 --- a/internal/services/compute/windows_virtual_machine_resource.go +++ b/internal/services/compute/windows_virtual_machine_resource.go @@ -1041,7 +1041,8 @@ func resourceWindowsVirtualMachineRead(d *pluginsdk.ResourceData, meta interface } if scheduleProfile := props.ScheduledEventsProfile; scheduleProfile != nil { - if err := d.Set("os_image_notification", flattenOsImageNotificationProfile(scheduleProfile.OsImageNotificationProfile)); err != nil { + _, isConfigured := d.GetOk("os_image_notification") + if err := d.Set("os_image_notification", flattenOsImageNotificationProfile(scheduleProfile.OsImageNotificationProfile, isConfigured)); err != nil { return fmt.Errorf("setting `termination_notification`: %+v", err) } diff --git a/internal/services/compute/windows_virtual_machine_resource_other_test.go b/internal/services/compute/windows_virtual_machine_resource_other_test.go index f9d4eae52a35..8ac324e76aea 100644 --- a/internal/services/compute/windows_virtual_machine_resource_other_test.go +++ b/internal/services/compute/windows_virtual_machine_resource_other_test.go @@ -752,7 +752,7 @@ func TestAccWindowsVirtualMachine_otherOsImageNotification(t *testing.T) { check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("true"), ), }, - data.ImportStep("admin_password"), + data.ImportStep("admin_password", "os_image_notification"), // turn termination notification off { Config: r.otherOsImageNotification(data, false), @@ -762,7 +762,7 @@ func TestAccWindowsVirtualMachine_otherOsImageNotification(t *testing.T) { check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("false"), ), }, - data.ImportStep("admin_password"), + data.ImportStep("admin_password", "os_image_notification"), // turn termination notification on again { Config: r.otherOsImageNotification(data, true), @@ -772,7 +772,7 @@ func TestAccWindowsVirtualMachine_otherOsImageNotification(t *testing.T) { check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("true"), ), }, - data.ImportStep("admin_password"), + data.ImportStep("admin_password", "os_image_notification"), }) } From 980e69378d9860741b8f337721a559bcc58f7e24 Mon Sep 17 00:00:00 2001 From: Zhenhua Hu Date: Fri, 1 Dec 2023 08:54:37 +0800 Subject: [PATCH 08/10] add comment --- internal/services/compute/linux_virtual_machine_resource.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/services/compute/linux_virtual_machine_resource.go b/internal/services/compute/linux_virtual_machine_resource.go index fc5be3d8d5f0..368354718297 100644 --- a/internal/services/compute/linux_virtual_machine_resource.go +++ b/internal/services/compute/linux_virtual_machine_resource.go @@ -407,6 +407,7 @@ func resourceLinuxVirtualMachine() *pluginsdk.Resource { } if features.FourPointOhBeta() { + // disk_controller_type is optional+computed, which may cause a diff after upgrading the provider. Make it take effect in next major version. resource.Schema["disk_controller_type"] = &pluginsdk.Schema{ Type: pluginsdk.TypeString, Optional: true, From 875251b0697ee1701bb80fe388939e5f85779cb4 Mon Sep 17 00:00:00 2001 From: Zhenhua Hu Date: Wed, 31 Jan 2024 17:01:38 +0800 Subject: [PATCH 09/10] resolve comments --- .../compute/linux_virtual_machine_resource.go | 3 +-- ...nux_virtual_machine_resource_other_test.go | 24 ++++++++----------- internal/services/compute/virtual_machine.go | 22 ++++------------- .../windows_virtual_machine_resource.go | 3 +-- ...ows_virtual_machine_resource_other_test.go | 24 ++++++++----------- .../r/linux_virtual_machine.html.markdown | 2 -- .../r/windows_virtual_machine.html.markdown | 2 -- 7 files changed, 27 insertions(+), 53 deletions(-) diff --git a/internal/services/compute/linux_virtual_machine_resource.go b/internal/services/compute/linux_virtual_machine_resource.go index 368354718297..d960b5d0b2c3 100644 --- a/internal/services/compute/linux_virtual_machine_resource.go +++ b/internal/services/compute/linux_virtual_machine_resource.go @@ -1001,8 +1001,7 @@ func resourceLinuxVirtualMachineRead(d *pluginsdk.ResourceData, meta interface{} } if scheduleProfile := props.ScheduledEventsProfile; scheduleProfile != nil { - _, isConfigured := d.GetOk("os_image_notification") - if err := d.Set("os_image_notification", flattenOsImageNotificationProfile(scheduleProfile.OsImageNotificationProfile, isConfigured)); err != nil { + if err := d.Set("os_image_notification", flattenOsImageNotificationProfile(scheduleProfile.OsImageNotificationProfile)); err != nil { return fmt.Errorf("setting `termination_notification`: %+v", err) } diff --git a/internal/services/compute/linux_virtual_machine_resource_other_test.go b/internal/services/compute/linux_virtual_machine_resource_other_test.go index fe593ca45bdf..f72738bb27c0 100644 --- a/internal/services/compute/linux_virtual_machine_resource_other_test.go +++ b/internal/services/compute/linux_virtual_machine_resource_other_test.go @@ -537,36 +537,29 @@ func TestAccLinuxVirtualMachine_otherOsImageNotification(t *testing.T) { r := LinuxVirtualMachineResource{} data.ResourceTest(t, r, []acceptance.TestStep{ - // turn termination notification on { Config: r.otherOsImageNotification(data, true), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"), - check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("true"), ), }, - data.ImportStep("os_image_notification"), - // turn termination notification off + data.ImportStep(), { Config: r.otherOsImageNotification(data, false), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), - check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"), - check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("false"), ), }, - data.ImportStep("os_image_notification"), - // turn termination notification on again + data.ImportStep(), { Config: r.otherOsImageNotification(data, true), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"), - check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("true"), ), }, - data.ImportStep("os_image_notification"), + data.ImportStep(), }) } @@ -2505,6 +2498,11 @@ resource "azurerm_linux_virtual_machine" "test" { } func (r LinuxVirtualMachineResource) otherOsImageNotification(data acceptance.TestData, enabled bool) string { + osImageNotificationConfig := "" + if enabled { + osImageNotificationConfig = "os_image_notification {}" + } + return fmt.Sprintf(` %s @@ -2535,11 +2533,9 @@ resource "azurerm_linux_virtual_machine" "test" { version = "latest" } - os_image_notification { - enabled = %t - } + %s } -`, r.template(data), data.RandomInteger, enabled) +`, r.template(data), data.RandomInteger, osImageNotificationConfig) } func (r LinuxVirtualMachineResource) otherTerminationNotification(data acceptance.TestData, enabled bool) string { diff --git a/internal/services/compute/virtual_machine.go b/internal/services/compute/virtual_machine.go index db8eaceb11b0..bccd2a9b0053 100644 --- a/internal/services/compute/virtual_machine.go +++ b/internal/services/compute/virtual_machine.go @@ -7,6 +7,7 @@ import ( "context" "fmt" + "github.com/hashicorp/go-azure-helpers/lang/pointer" "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-helpers/resourcemanager/identity" "github.com/hashicorp/go-azure-sdk/resource-manager/compute/2022-03-03/galleryapplicationversions" @@ -432,10 +433,6 @@ func virtualMachineOsImageNotificationSchema() *pluginsdk.Schema { MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "enabled": { - Type: pluginsdk.TypeBool, - Required: true, - }, "timeout": { Type: pluginsdk.TypeString, Optional: true, @@ -480,11 +477,10 @@ func expandOsImageNotificationProfile(input []interface{}) *compute.OSImageNotif } raw := input[0].(map[string]interface{}) - enabled := raw["enabled"].(bool) timeout := raw["timeout"].(string) return &compute.OSImageNotificationProfile{ - Enable: &enabled, + Enable: utils.Bool(true), NotBeforeTimeout: &timeout, } } @@ -506,26 +502,18 @@ func expandTerminateNotificationProfile(input []interface{}) *compute.TerminateN } } -func flattenOsImageNotificationProfile(input *compute.OSImageNotificationProfile, isConfigured bool) []interface{} { - if input == nil && !isConfigured { +func flattenOsImageNotificationProfile(input *compute.OSImageNotificationProfile) []interface{} { + if input == nil || !pointer.From(input.Enable) { return nil } - // if enabled is set to false, there will be no ScheduledEventsProfile in response, to avoid plan non empty when - // a user explicitly set enabled to false, we need to assign a default block to this field - enabled := false - if input != nil && input.Enable != nil { - enabled = *input.Enable - } - timeout := "PT15M" - if input != nil && input.NotBeforeTimeout != nil { + if input.NotBeforeTimeout != nil { timeout = *input.NotBeforeTimeout } return []interface{}{ map[string]interface{}{ - "enabled": enabled, "timeout": timeout, }, } diff --git a/internal/services/compute/windows_virtual_machine_resource.go b/internal/services/compute/windows_virtual_machine_resource.go index 3fba2eb1f4e0..d559b44cf209 100644 --- a/internal/services/compute/windows_virtual_machine_resource.go +++ b/internal/services/compute/windows_virtual_machine_resource.go @@ -1041,8 +1041,7 @@ func resourceWindowsVirtualMachineRead(d *pluginsdk.ResourceData, meta interface } if scheduleProfile := props.ScheduledEventsProfile; scheduleProfile != nil { - _, isConfigured := d.GetOk("os_image_notification") - if err := d.Set("os_image_notification", flattenOsImageNotificationProfile(scheduleProfile.OsImageNotificationProfile, isConfigured)); err != nil { + if err := d.Set("os_image_notification", flattenOsImageNotificationProfile(scheduleProfile.OsImageNotificationProfile)); err != nil { return fmt.Errorf("setting `termination_notification`: %+v", err) } diff --git a/internal/services/compute/windows_virtual_machine_resource_other_test.go b/internal/services/compute/windows_virtual_machine_resource_other_test.go index 8ac324e76aea..fde2e0df69f8 100644 --- a/internal/services/compute/windows_virtual_machine_resource_other_test.go +++ b/internal/services/compute/windows_virtual_machine_resource_other_test.go @@ -743,36 +743,29 @@ func TestAccWindowsVirtualMachine_otherOsImageNotification(t *testing.T) { r := WindowsVirtualMachineResource{} data.ResourceTest(t, r, []acceptance.TestStep{ - // turn termination notification on { Config: r.otherOsImageNotification(data, true), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"), - check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("true"), ), }, - data.ImportStep("admin_password", "os_image_notification"), - // turn termination notification off + data.ImportStep("admin_password"), { Config: r.otherOsImageNotification(data, false), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), - check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"), - check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("false"), ), }, - data.ImportStep("admin_password", "os_image_notification"), - // turn termination notification on again + data.ImportStep("admin_password"), { Config: r.otherOsImageNotification(data, true), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"), - check.That(data.ResourceName).Key("os_image_notification.0.enabled").HasValue("true"), ), }, - data.ImportStep("admin_password", "os_image_notification"), + data.ImportStep("admin_password"), }) } @@ -2883,6 +2876,11 @@ resource "azurerm_windows_virtual_machine" "test" { } func (r WindowsVirtualMachineResource) otherOsImageNotification(data acceptance.TestData, enabled bool) string { + osImageNotificationConfig := "" + if enabled { + osImageNotificationConfig = "os_image_notification {}" + } + return fmt.Sprintf(` %s @@ -2909,11 +2907,9 @@ resource "azurerm_windows_virtual_machine" "test" { version = "latest" } - os_image_notification { - enabled = %t - } + %s } -`, r.template(data), enabled) +`, r.template(data), osImageNotificationConfig) } func (r WindowsVirtualMachineResource) otherTerminationNotification(data acceptance.TestData, enabled bool) string { diff --git a/website/docs/r/linux_virtual_machine.html.markdown b/website/docs/r/linux_virtual_machine.html.markdown index 9d58c2f09501..2315ee2dcc92 100644 --- a/website/docs/r/linux_virtual_machine.html.markdown +++ b/website/docs/r/linux_virtual_machine.html.markdown @@ -360,8 +360,6 @@ The `source_image_reference` block supports the following: A `os_image_notification` block supports the following: -* `enabled` - (Required) Should the OS image notification be enabled on this Virtual Machine? - * `timeout` - (Optional) Length of time a notification to be sent to the VM on the instance metadata server till the VM gets OS upgraded. The only possible value is `PT15M`. Defaults to `PT15M`. --- diff --git a/website/docs/r/windows_virtual_machine.html.markdown b/website/docs/r/windows_virtual_machine.html.markdown index 83ad257a1f82..160426b11538 100644 --- a/website/docs/r/windows_virtual_machine.html.markdown +++ b/website/docs/r/windows_virtual_machine.html.markdown @@ -361,8 +361,6 @@ The `source_image_reference` block supports the following: A `os_image_notification` block supports the following: -* `enabled` - (Required) Should the OS image notification be enabled on this Virtual Machine? - * `timeout` - (Optional) Length of time a notification to be sent to the VM on the instance metadata server till the VM gets OS upgraded. The only possible value is `PT15M`. Defaults to `PT15M`. --- From e1b104248ca69281e59b8e234694a82faf1590e5 Mon Sep 17 00:00:00 2001 From: Zhenhua Hu Date: Thu, 22 Feb 2024 11:01:11 +0800 Subject: [PATCH 10/10] remove version limitation --- .../compute/linux_virtual_machine_resource.go | 53 ++++++++----------- ...x_virtual_machine_resource_disk_os_test.go | 5 -- .../windows_virtual_machine_resource.go | 52 ++++++++---------- ...s_virtual_machine_resource_disk_os_test.go | 5 -- .../r/linux_virtual_machine.html.markdown | 2 - .../r/windows_virtual_machine.html.markdown | 2 - 6 files changed, 42 insertions(+), 77 deletions(-) diff --git a/internal/services/compute/linux_virtual_machine_resource.go b/internal/services/compute/linux_virtual_machine_resource.go index d960b5d0b2c3..e02b975d60a3 100644 --- a/internal/services/compute/linux_virtual_machine_resource.go +++ b/internal/services/compute/linux_virtual_machine_resource.go @@ -24,7 +24,6 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" azValidate "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - "github.com/hashicorp/terraform-provider-azurerm/internal/features" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse" computeValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate" @@ -40,7 +39,7 @@ import ( ) func resourceLinuxVirtualMachine() *pluginsdk.Resource { - resource := &pluginsdk.Resource{ + return &pluginsdk.Resource{ Create: resourceLinuxVirtualMachineCreate, Read: resourceLinuxVirtualMachineRead, Update: resourceLinuxVirtualMachineUpdate, @@ -195,6 +194,16 @@ func resourceLinuxVirtualMachine() *pluginsdk.Resource { Default: true, }, + "disk_controller_type": { + Type: pluginsdk.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{ + string(compute.DiskControllerTypesNVMe), + string(compute.DiskControllerTypesSCSI), + }, false), + }, + "edge_zone": commonschema.EdgeZoneOptionalForceNew(), "encryption_at_host_enabled": { @@ -405,20 +414,6 @@ func resourceLinuxVirtualMachine() *pluginsdk.Resource { }, }, } - - if features.FourPointOhBeta() { - // disk_controller_type is optional+computed, which may cause a diff after upgrading the provider. Make it take effect in next major version. - resource.Schema["disk_controller_type"] = &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - string(compute.DiskControllerTypesNVMe), - string(compute.DiskControllerTypesSCSI), - }, false), - } - } - - return resource } func resourceLinuxVirtualMachineCreate(d *pluginsdk.ResourceData, meta interface{}) error { @@ -545,10 +540,8 @@ func resourceLinuxVirtualMachineCreate(d *pluginsdk.ResourceData, meta interface Tags: tags.Expand(t), } - if features.FourPointOhBeta() { - if diskControllerType, ok := d.GetOk("disk_controller_type"); ok { - params.StorageProfile.DiskControllerType = compute.DiskControllerTypes(diskControllerType.(string)) - } + if diskControllerType, ok := d.GetOk("disk_controller_type"); ok { + params.StorageProfile.DiskControllerType = compute.DiskControllerTypes(diskControllerType.(string)) } if encryptionAtHostEnabled, ok := d.GetOk("encryption_at_host_enabled"); ok { @@ -969,9 +962,7 @@ func resourceLinuxVirtualMachineRead(d *pluginsdk.ResourceData, meta interface{} d.Set("proximity_placement_group_id", proximityPlacementGroupId) if profile := props.StorageProfile; profile != nil { - if features.FourPointOhBeta() { - d.Set("disk_controller_type", string(props.StorageProfile.DiskControllerType)) - } + d.Set("disk_controller_type", string(props.StorageProfile.DiskControllerType)) // the storage_account_type isn't returned so we need to look it up flattenedOSDisk, err := flattenVirtualMachineOSDisk(ctx, disksClient, profile.OsDisk) @@ -1233,17 +1224,15 @@ func resourceLinuxVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interface } } - if features.FourPointOhBeta() { - if d.HasChange("disk_controller_type") { - shouldUpdate = true - shouldDeallocate = true - - if update.VirtualMachineProperties.StorageProfile == nil { - update.VirtualMachineProperties.StorageProfile = &compute.StorageProfile{} - } + if d.HasChange("disk_controller_type") { + shouldUpdate = true + shouldDeallocate = true - update.VirtualMachineProperties.StorageProfile.DiskControllerType = compute.DiskControllerTypes(d.Get("disk_controller_type").(string)) + if update.VirtualMachineProperties.StorageProfile == nil { + update.VirtualMachineProperties.StorageProfile = &compute.StorageProfile{} } + + update.VirtualMachineProperties.StorageProfile.DiskControllerType = compute.DiskControllerTypes(d.Get("disk_controller_type").(string)) } if d.HasChange("os_disk") { diff --git a/internal/services/compute/linux_virtual_machine_resource_disk_os_test.go b/internal/services/compute/linux_virtual_machine_resource_disk_os_test.go index d6150adff12e..33e21b48552d 100644 --- a/internal/services/compute/linux_virtual_machine_resource_disk_os_test.go +++ b/internal/services/compute/linux_virtual_machine_resource_disk_os_test.go @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" - "github.com/hashicorp/terraform-provider-azurerm/internal/features" ) func TestAccLinuxVirtualMachine_diskOSBasic(t *testing.T) { @@ -302,10 +301,6 @@ func TestAccLinuxVirtualMachine_diskOSStorageTypeUpdate(t *testing.T) { } func TestAccLinuxVirtualMachine_diskOSControllerType(t *testing.T) { - if !features.FourPointOhBeta() { - t.Skipf("Test applies after 4.0 only") - } - data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine", "test") r := LinuxVirtualMachineResource{} diff --git a/internal/services/compute/windows_virtual_machine_resource.go b/internal/services/compute/windows_virtual_machine_resource.go index d559b44cf209..d9b29cc6ec12 100644 --- a/internal/services/compute/windows_virtual_machine_resource.go +++ b/internal/services/compute/windows_virtual_machine_resource.go @@ -25,7 +25,6 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" azValidate "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - "github.com/hashicorp/terraform-provider-azurerm/internal/features" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse" computeValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate" @@ -41,7 +40,7 @@ import ( ) func resourceWindowsVirtualMachine() *pluginsdk.Resource { - resource := &pluginsdk.Resource{ + return &pluginsdk.Resource{ Create: resourceWindowsVirtualMachineCreate, Read: resourceWindowsVirtualMachineRead, Update: resourceWindowsVirtualMachineUpdate, @@ -190,6 +189,16 @@ func resourceWindowsVirtualMachine() *pluginsdk.Resource { }, }, + "disk_controller_type": { + Type: pluginsdk.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{ + string(compute.DiskControllerTypesNVMe), + string(compute.DiskControllerTypesSCSI), + }, false), + }, + "edge_zone": commonschema.EdgeZoneOptionalForceNew(), // TODO 4.0: change this from enable_* to *_enabled @@ -432,19 +441,6 @@ func resourceWindowsVirtualMachine() *pluginsdk.Resource { }, }, } - - if features.FourPointOhBeta() { - resource.Schema["disk_controller_type"] = &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - string(compute.DiskControllerTypesNVMe), - string(compute.DiskControllerTypesSCSI), - }, false), - } - } - - return resource } func resourceWindowsVirtualMachineCreate(d *pluginsdk.ResourceData, meta interface{}) error { @@ -580,10 +576,8 @@ func resourceWindowsVirtualMachineCreate(d *pluginsdk.ResourceData, meta interfa Tags: tags.Expand(t), } - if features.FourPointOhBeta() { - if diskControllerType, ok := d.GetOk("disk_controller_type"); ok { - params.StorageProfile.DiskControllerType = compute.DiskControllerTypes(diskControllerType.(string)) - } + if diskControllerType, ok := d.GetOk("disk_controller_type"); ok { + params.StorageProfile.DiskControllerType = compute.DiskControllerTypes(diskControllerType.(string)) } if !provisionVMAgent && allowExtensionOperations { @@ -1010,9 +1004,7 @@ func resourceWindowsVirtualMachineRead(d *pluginsdk.ResourceData, meta interface d.Set("proximity_placement_group_id", proximityPlacementGroupId) if profile := props.StorageProfile; profile != nil { - if features.FourPointOhBeta() { - d.Set("disk_controller_type", string(props.StorageProfile.DiskControllerType)) - } + d.Set("disk_controller_type", string(props.StorageProfile.DiskControllerType)) // the storage_account_type isn't returned so we need to look it up flattenedOSDisk, err := flattenVirtualMachineOSDisk(ctx, disksClient, profile.OsDisk) @@ -1406,17 +1398,15 @@ func resourceWindowsVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interfa } } - if features.FourPointOhBeta() { - if d.HasChange("disk_controller_type") { - shouldUpdate = true - shouldDeallocate = true - - if update.VirtualMachineProperties.StorageProfile == nil { - update.VirtualMachineProperties.StorageProfile = &compute.StorageProfile{} - } + if d.HasChange("disk_controller_type") { + shouldUpdate = true + shouldDeallocate = true - update.VirtualMachineProperties.StorageProfile.DiskControllerType = compute.DiskControllerTypes(d.Get("disk_controller_type").(string)) + if update.VirtualMachineProperties.StorageProfile == nil { + update.VirtualMachineProperties.StorageProfile = &compute.StorageProfile{} } + + update.VirtualMachineProperties.StorageProfile.DiskControllerType = compute.DiskControllerTypes(d.Get("disk_controller_type").(string)) } if d.HasChange("os_disk") { diff --git a/internal/services/compute/windows_virtual_machine_resource_disk_os_test.go b/internal/services/compute/windows_virtual_machine_resource_disk_os_test.go index d0d064986a16..939c0d7f6a4d 100644 --- a/internal/services/compute/windows_virtual_machine_resource_disk_os_test.go +++ b/internal/services/compute/windows_virtual_machine_resource_disk_os_test.go @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" - "github.com/hashicorp/terraform-provider-azurerm/internal/features" ) func TestAccWindowsVirtualMachine_diskOSBasic(t *testing.T) { @@ -302,10 +301,6 @@ func TestAccWindowsVirtualMachine_diskOSStorageTypeUpdate(t *testing.T) { } func TestAccWindowsVirtualMachine_diskOSControllerType(t *testing.T) { - if !features.FourPointOhBeta() { - t.Skipf("Test applies after 4.0 only") - } - data := acceptance.BuildTestData(t, "azurerm_windows_virtual_machine", "test") r := WindowsVirtualMachineResource{} diff --git a/website/docs/r/linux_virtual_machine.html.markdown b/website/docs/r/linux_virtual_machine.html.markdown index 2315ee2dcc92..2bfbcde46e16 100644 --- a/website/docs/r/linux_virtual_machine.html.markdown +++ b/website/docs/r/linux_virtual_machine.html.markdown @@ -150,8 +150,6 @@ The following arguments are supported: * `disk_controller_type` - (Optional) Specifies the Disk Controller Type used for this Virtual Machine. Possible values are `SCSI` and `NVMe`. --> **Note:** This will be available only from the next major version of the Azure Provider (4.0). - * `edge_zone` - (Optional) Specifies the Edge Zone within the Azure Region where this Linux Virtual Machine should exist. Changing this forces a new Linux Virtual Machine to be created. * `encryption_at_host_enabled` - (Optional) Should all of the disks (including the temp disk) attached to this Virtual Machine be encrypted by enabling Encryption at Host? diff --git a/website/docs/r/windows_virtual_machine.html.markdown b/website/docs/r/windows_virtual_machine.html.markdown index 160426b11538..ec232b596756 100644 --- a/website/docs/r/windows_virtual_machine.html.markdown +++ b/website/docs/r/windows_virtual_machine.html.markdown @@ -139,8 +139,6 @@ The following arguments are supported: * `disk_controller_type` - (Optional) Specifies the Disk Controller Type used for this Virtual Machine. Possible values are `SCSI` and `NVMe`. --> **Note:** This will be available only from the next major version of the Azure Provider (4.0). - * `enable_automatic_updates` - (Optional) Specifies if Automatic Updates are Enabled for the Windows Virtual Machine. Changing this forces a new resource to be created. Defaults to `true`. * `encryption_at_host_enabled` - (Optional) Should all of the disks (including the temp disk) attached to this Virtual Machine be encrypted by enabling Encryption at Host?