diff --git a/internal/services/compute/client/helper.go b/internal/services/compute/client/helper.go new file mode 100644 index 000000000000..05b23b6419ae --- /dev/null +++ b/internal/services/compute/client/helper.go @@ -0,0 +1,30 @@ +package client + +import ( + "context" + "fmt" + "log" + "net/http" + "strings" +) + +func (c *Client) CancelRollingUpgradesBeforeDeletion(ctx context.Context, resourceGroupName string, vmScaleSetName string) error { + future, err := c.VMScaleSetRollingUpgradesClient.Cancel(ctx, resourceGroupName, vmScaleSetName) + + // If rolling upgrades haven't been run (when VMSS are just provisioned with rolling upgrades but no extensions, auto-scaling are run ) + // we can not cancel rolling upgrades + // API call :: GET https://management.azure.com/subscriptions/{subId}/resourceGroups/{rgName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmSSName}/rollingUpgrades/latest?api-version=2021-07-01 + // Azure API throws 409 conflict error saying "The entity was not found in this Azure location." + // If the above error message matches, we identify and move forward to delete the VMSS + // in all other cases, it just cancels the rolling upgrades and move ahead to delete the VMSS + if err != nil && !(future.Response().StatusCode == http.StatusConflict && strings.Contains(err.Error(), "There is no ongoing Rolling Upgrade to cancel.")) { + return fmt.Errorf("error cancelling rolling upgrades of Virtual Machine Scale Set %q (Resource Group %q): %+v", vmScaleSetName, resourceGroupName, err) + } + + log.Printf("[DEBUG] Waiting for deletion of Virtual Machine Scale Set %q (Resource Group %q)..", vmScaleSetName, resourceGroupName) + if err := future.WaitForCompletionRef(ctx, c.VMScaleSetExtensionsClient.Client); err != nil && !(future.Response().StatusCode == http.StatusConflict && strings.Contains(err.Error(), "There is no ongoing Rolling Upgrade to cancel.")) { + return fmt.Errorf("waiting for cancelling rolling upgrades of Virtual Machine Scale Set %q (Resource Group %q): %+v", vmScaleSetName, resourceGroupName, err) + } + log.Printf("[DEBUG] cancelled Virtual Machine Scale Set Rolling Upgrades %q (Resource Group %q).", vmScaleSetName, resourceGroupName) + return nil +} diff --git a/internal/services/compute/linux_virtual_machine_scale_set_resource.go b/internal/services/compute/linux_virtual_machine_scale_set_resource.go index 668349812817..20a842c33e72 100644 --- a/internal/services/compute/linux_virtual_machine_scale_set_resource.go +++ b/internal/services/compute/linux_virtual_machine_scale_set_resource.go @@ -103,6 +103,12 @@ func resourceLinuxVirtualMachineScaleSet() *pluginsdk.Resource { "boot_diagnostics": bootDiagnosticsSchema(), + "cancel_rolling_upgrades_before_deletion": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + "computer_name_prefix": { Type: pluginsdk.TypeString, Optional: true, @@ -1153,6 +1159,14 @@ func resourceLinuxVirtualMachineScaleSetDelete(d *pluginsdk.ResourceData, meta i return err } + cancelRollingUpgradesBeforeDeletion := d.Get("cancel_rolling_upgrades_before_deletion").(bool) + if cancelRollingUpgradesBeforeDeletion { + err := meta.(*clients.Client).Compute.CancelRollingUpgradesBeforeDeletion(ctx, id.ResourceGroup, id.Name) + if err != nil { + return err + } + } + // Upgrading to the 2021-07-01 exposed a new expand parameter to the GET method resp, err := client.Get(ctx, id.ResourceGroup, id.Name, compute.ExpandTypesForGetVMScaleSetsUserData) if err != nil { diff --git a/internal/services/compute/virtual_machine_scale_set_extension_resource.go b/internal/services/compute/virtual_machine_scale_set_extension_resource.go index 21f653ade4f2..9f0a58bae90f 100644 --- a/internal/services/compute/virtual_machine_scale_set_extension_resource.go +++ b/internal/services/compute/virtual_machine_scale_set_extension_resource.go @@ -110,6 +110,12 @@ func resourceVirtualMachineScaleSetExtension() *pluginsdk.Resource { ValidateFunc: validation.StringIsJSON, DiffSuppressFunc: pluginsdk.SuppressJsonDiff, }, + + "cancel_rolling_upgrades_before_deletion": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, }, } } @@ -341,6 +347,14 @@ func resourceVirtualMachineScaleSetExtensionDelete(d *pluginsdk.ResourceData, me return err } + cancelRollingUpgradesBeforeDeletion := d.Get("cancel_rolling_upgrades_before_deletion").(bool) + if cancelRollingUpgradesBeforeDeletion { + err := meta.(*clients.Client).Compute.CancelRollingUpgradesBeforeDeletion(ctx, id.ResourceGroup, id.VirtualMachineScaleSetName) + if err != nil { + return err + } + } + future, err := client.Delete(ctx, id.ResourceGroup, id.VirtualMachineScaleSetName, id.ExtensionName) if err != nil { return fmt.Errorf("deleting Extension %q (Virtual Machine Scale Set %q / Resource Group %q): %+v", id.ExtensionName, id.VirtualMachineScaleSetName, id.ResourceGroup, err) diff --git a/internal/services/compute/windows_virtual_machine_scale_set_resource.go b/internal/services/compute/windows_virtual_machine_scale_set_resource.go index 77daf4034dc6..b3b6ab268b43 100644 --- a/internal/services/compute/windows_virtual_machine_scale_set_resource.go +++ b/internal/services/compute/windows_virtual_machine_scale_set_resource.go @@ -107,6 +107,12 @@ func resourceWindowsVirtualMachineScaleSet() *pluginsdk.Resource { "boot_diagnostics": bootDiagnosticsSchema(), + "cancel_rolling_upgrades_before_deletion": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + "computer_name_prefix": { Type: pluginsdk.TypeString, Optional: true, @@ -1219,6 +1225,14 @@ func resourceWindowsVirtualMachineScaleSetDelete(d *pluginsdk.ResourceData, meta return err } + cancelRollingUpgradesBeforeDeletion := d.Get("cancel_rolling_upgrades_before_deletion").(bool) + if cancelRollingUpgradesBeforeDeletion { + err := meta.(*clients.Client).Compute.CancelRollingUpgradesBeforeDeletion(ctx, id.ResourceGroup, id.Name) + if err != nil { + return err + } + } + resp, err := client.Get(ctx, id.ResourceGroup, id.Name, "") if err != nil { if utils.ResponseWasNotFound(resp.Response) { diff --git a/website/docs/r/linux_virtual_machine_scale_set.html.markdown b/website/docs/r/linux_virtual_machine_scale_set.html.markdown index ab0d03ad0b45..c960fbb434a7 100644 --- a/website/docs/r/linux_virtual_machine_scale_set.html.markdown +++ b/website/docs/r/linux_virtual_machine_scale_set.html.markdown @@ -128,6 +128,8 @@ The following arguments are supported: * `boot_diagnostics` - (Optional) A `boot_diagnostics` block as defined below. +* `cancel_rolling_upgrades_before_deletion` - (Optional) Cancel Rolling Upgrades before deleting the VM ScaleSets during destroy phase. Defaults to false. + * `computer_name_prefix` - (Optional) The prefix which should be used for the name of the Virtual Machines in this Scale Set. If unspecified this defaults to the value for the `name` field. If the value of the `name` field is not a valid `computer_name_prefix`, then you must specify `computer_name_prefix`. * `custom_data` - (Optional) The Base64-Encoded Custom Data which should be used for this Virtual Machine Scale Set. diff --git a/website/docs/r/virtual_machine_scale_set_extension.html.markdown b/website/docs/r/virtual_machine_scale_set_extension.html.markdown index 2a43340c527a..61331207a07c 100644 --- a/website/docs/r/virtual_machine_scale_set_extension.html.markdown +++ b/website/docs/r/virtual_machine_scale_set_extension.html.markdown @@ -47,6 +47,8 @@ The following arguments are supported: * `type_handler_version` - (Required) Specifies the version of the extension to use, available versions can be found using the Azure CLI. +* `cancel_rolling_upgrades_before_deletion` - (Optional) Cancel Rolling Upgrades before deleting the VMSS extensions during destroy phase. Defaults to false. + ~> **Note:** The `Publisher` and `Type` of Virtual Machine Scale Set Extensions can be found using the Azure CLI, via: ```shell 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 1ffcff8a292a..413c9b0e2b1d 100644 --- a/website/docs/r/windows_virtual_machine_scale_set.html.markdown +++ b/website/docs/r/windows_virtual_machine_scale_set.html.markdown @@ -120,6 +120,8 @@ The following arguments are supported: * `boot_diagnostics` - (Optional) A `boot_diagnostics` block as defined below. +* `cancel_rolling_upgrades_before_deletion` - (Optional) Cancel Rolling Upgrades before deleting the VM ScaleSets during destroy phase. Defaults to false. + * `computer_name_prefix` - (Optional) The prefix which should be used for the name of the Virtual Machines in this Scale Set. If unspecified this defaults to the value for the `name` field. If the value of the `name` field is not a valid `computer_name_prefix`, then you must specify `computer_name_prefix`. * `custom_data` - (Optional) The Base64-Encoded Custom Data which should be used for this Virtual Machine Scale Set.