From bacabc6f4e934174e5680d82efac054405272a34 Mon Sep 17 00:00:00 2001 From: Henry Buckle Date: Sat, 15 May 2021 07:25:14 +0100 Subject: [PATCH] allow updating vmss license --- ...l_machine_scale_set_other_resource_test.go | 115 ++++++++++++++++++ ...dows_virtual_machine_scale_set_resource.go | 19 ++- ...ws_virtual_machine_scale_set.html.markdown | 2 +- 3 files changed, 134 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/compute/windows_virtual_machine_scale_set_other_resource_test.go b/azurerm/internal/services/compute/windows_virtual_machine_scale_set_other_resource_test.go index 3e09cd30b620..6bcd35d55bca 100644 --- a/azurerm/internal/services/compute/windows_virtual_machine_scale_set_other_resource_test.go +++ b/azurerm/internal/services/compute/windows_virtual_machine_scale_set_other_resource_test.go @@ -730,6 +730,42 @@ func TestAccWindowsVirtualMachineScaleSet_otherHealthProbeUpdate(t *testing.T) { }) } +func TestAccWindowsVirtualMachineScaleSet_otherLicenseTypeUpdated(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_windows_virtual_machine_scale_set", "test") + r := WindowsVirtualMachineScaleSetResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.otherLicenseTypeDefault(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep( + "admin_password", + ), + { + Config: r.otherLicenseType(data, "Windows_Client"), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("license_type").HasValue("Windows_Client"), + ), + }, + data.ImportStep( + "admin_password", + ), + { + Config: r.otherLicenseTypeDefault(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep( + "admin_password", + ), + }) +} + func (WindowsVirtualMachineScaleSetResource) otherAdditionalUnattendContent(data acceptance.TestData) string { template := WindowsVirtualMachineScaleSetResource{}.template(data) return fmt.Sprintf(` @@ -2788,3 +2824,82 @@ resource "azurerm_windows_virtual_machine_scale_set" "test" { } `, r.template(data), data.RandomInteger) } + +func (r WindowsVirtualMachineScaleSetResource) otherLicenseTypeDefault(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_windows_virtual_machine_scale_set" "test" { + name = local.vm_name + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sku = "Standard_F2" + instances = 1 + admin_username = "adminuser" + admin_password = "P@ssword1234!" + + source_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2019-Datacenter" + version = "latest" + } + + os_disk { + storage_account_type = "Standard_LRS" + caching = "ReadWrite" + } + + network_interface { + name = "example" + primary = true + + ip_configuration { + name = "internal" + primary = true + subnet_id = azurerm_subnet.test.id + } + } +} +`, r.template(data)) +} + +func (r WindowsVirtualMachineScaleSetResource) otherLicenseType(data acceptance.TestData, licenseType string) string { + return fmt.Sprintf(` +%s + +resource "azurerm_windows_virtual_machine_scale_set" "test" { + name = local.vm_name + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sku = "Standard_F2" + instances = 1 + admin_username = "adminuser" + admin_password = "P@ssword1234!" + license_type = %q + + source_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2019-Datacenter" + version = "latest" + } + + os_disk { + storage_account_type = "Standard_LRS" + caching = "ReadWrite" + } + + network_interface { + name = "example" + primary = true + + ip_configuration { + name = "internal" + primary = true + subnet_id = azurerm_subnet.test.id + } + } +} +`, r.template(data), licenseType) +} diff --git a/azurerm/internal/services/compute/windows_virtual_machine_scale_set_resource.go b/azurerm/internal/services/compute/windows_virtual_machine_scale_set_resource.go index 84025e84cb64..80721ec59d0d 100644 --- a/azurerm/internal/services/compute/windows_virtual_machine_scale_set_resource.go +++ b/azurerm/internal/services/compute/windows_virtual_machine_scale_set_resource.go @@ -163,12 +163,18 @@ func resourceWindowsVirtualMachineScaleSet() *schema.Resource { "license_type": { Type: schema.TypeString, Optional: true, - ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ "None", "Windows_Client", "Windows_Server", }, false), + DiffSuppressFunc: func(_, old, new string, _ *schema.ResourceData) bool { + if old == "None" && new == "" || old == "" && new == "None" { + return true + } + + return false + }, }, "max_bid_price": { @@ -809,6 +815,17 @@ func resourceWindowsVirtualMachineScaleSetUpdate(d *schema.ResourceData, meta in } } + if d.HasChange("license_type") { + license := d.Get("license_type").(string) + if license == "" { + // Only for create no specification is possible in the API. API does not allow empty string in update. + // So removing attribute license_type from Terraform configuration if it was set to value other than 'None' would lead to an endless loop in apply. + // To allow updating in this case set value explicitly to 'None'. + license = "None" + } + updateProps.VirtualMachineProfile.LicenseType = &license + } + if d.HasChange("automatic_instance_repair") { automaticRepairsPolicyRaw := d.Get("automatic_instance_repair").([]interface{}) automaticRepairsPolicy := ExpandVirtualMachineScaleSetAutomaticRepairsPolicy(automaticRepairsPolicyRaw) diff --git a/website/docs/r/windows_virtual_machine_scale_set.html.markdown b/website/docs/r/windows_virtual_machine_scale_set.html.markdown index d45ba6cf4ec4..0056776f06f9 100644 --- a/website/docs/r/windows_virtual_machine_scale_set.html.markdown +++ b/website/docs/r/windows_virtual_machine_scale_set.html.markdown @@ -144,7 +144,7 @@ The following arguments are supported: * `identity` - (Optional) A `identity` block as defined below. -* `license_type` - (Optional) Specifies the type of on-premise license (also known as [Azure Hybrid Use Benefit](https://docs.microsoft.com/azure/virtual-machines/virtual-machines-windows-hybrid-use-benefit-licensing)) which should be used for this Virtual Machine Scale Set. Possible values are `None`, `Windows_Client` and `Windows_Server`. Changing this forces a new resource to be created. +* `license_type` - (Optional) Specifies the type of on-premise license (also known as [Azure Hybrid Use Benefit](https://docs.microsoft.com/azure/virtual-machines/virtual-machines-windows-hybrid-use-benefit-licensing)) which should be used for this Virtual Machine Scale Set. Possible values are `None`, `Windows_Client` and `Windows_Server`. * `max_bid_price` - (Optional) The maximum price you're willing to pay for each Virtual Machine in this Scale Set, in US Dollars; which must be greater than the current spot price. If this bid price falls below the current spot price the Virtual Machines in the Scale Set will be evicted using the `eviction_policy`. Defaults to `-1`, which means that each Virtual Machine in the Scale Set should not be evicted for price reasons.