Skip to content

Commit

Permalink
azurerm_backup_protected_vm - fix a bug during deletion (#20469)
Browse files Browse the repository at this point in the history
  • Loading branch information
ziyeqf authored Feb 15, 2023
1 parent 74a82a6 commit 0b810d8
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 17 deletions.
40 changes: 23 additions & 17 deletions internal/services/recoveryservices/backup_protected_vm_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -172,7 +173,7 @@ func resourceRecoveryServicesBackupProtectedVMRead(d *pluginsdk.ResourceData, me

func resourceRecoveryServicesBackupProtectedVMDelete(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).RecoveryServices.ProtectedItemsClient
containerClient := meta.(*clients.Client).RecoveryServices.BackupProtectionContainersClient
opResultClient := meta.(*clients.Client).RecoveryServices.BackupOperationResultsClient
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
defer cancel()

Expand All @@ -190,7 +191,17 @@ func resourceRecoveryServicesBackupProtectedVMDelete(d *pluginsdk.ResourceData,
}
}

if _, err := resourceRecoveryServicesBackupProtectedVMWaitForDeletion(ctx, client, containerClient, id.VaultName, id.ResourceGroup, id.ProtectionContainerName, id.Name, d); err != nil {
locationURL, err := resp.Response.Location()
if err != nil || locationURL == nil {
return fmt.Errorf("deleting %s: Location header missing or empty", id)
}

parsedLocation, err := azure.ParseAzureResourceID(handleAzureSdkForGoBug2824(locationURL.Path))
if err != nil {
return err
}

if _, err := resourceRecoveryServicesBackupProtectedVMWaitForDeletion(ctx, client, opResultClient, id.VaultName, id.ResourceGroup, id.ProtectionContainerName, id.Name, parsedLocation.Path["backupOperationResults"], d); err != nil {
return err
}

Expand Down Expand Up @@ -221,7 +232,7 @@ func resourceRecoveryServicesBackupProtectedVMWaitForStateCreateUpdate(ctx conte
return resp.(backup.ProtectedItemResource), nil
}

func resourceRecoveryServicesBackupProtectedVMWaitForDeletion(ctx context.Context, client *backup.ProtectedItemsClient, containerClient *backup.ProtectionContainersClient, vaultName, resourceGroup, containerName, protectedItemName string, d *pluginsdk.ResourceData) (backup.ProtectedItemResource, error) {
func resourceRecoveryServicesBackupProtectedVMWaitForDeletion(ctx context.Context, client *backup.ProtectedItemsClient, opResultClient *backup.OperationResultsClient, vaultName, resourceGroup, containerName, protectedItemName, operationId string, d *pluginsdk.ResourceData) (backup.ProtectedItemResource, error) {
state := &pluginsdk.StateChangeConf{
MinTimeout: 30 * time.Second,
Delay: 10 * time.Second,
Expand Down Expand Up @@ -256,31 +267,26 @@ func resourceRecoveryServicesBackupProtectedVMWaitForDeletion(ctx context.Contex
return i, fmt.Errorf("waiting for the Azure Backup Protected VM %q to be deleted (Resource Group %q): %+v", protectedItemName, resourceGroup, err)
}

// besides waiting for the protected item to be fully deleted, it's also needed to wait for the protection container to be unregistered, or it will fail when creating another backup for the same vm in another recovery vault.
containerState := &pluginsdk.StateChangeConf{
// we should also wait for the operation to complete, or it will fail when creating a new backup vm with the same vm in different vault immediately.
opState := &pluginsdk.StateChangeConf{
MinTimeout: 30 * time.Second,
Delay: 10 * time.Second,
Pending: []string{"Pending"},
Target: []string{"NotFound"},
Pending: []string{"202"},
Target: []string{"200", "204"},
Refresh: func() (interface{}, string, error) {
resp, err := containerClient.Get(ctx, vaultName, resourceGroup, "Azure", containerName)
resp, err := opResultClient.Get(ctx, vaultName, resourceGroup, operationId)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return resp, "NotFound", nil
}

return resp, "Error", fmt.Errorf("making Read request on Azure Backup Protection Container %q (Resource Group %q): %+v", protectedItemName, resourceGroup, err)
return nil, "Error", fmt.Errorf("making Read request on Recovery Service Protected Item operation %q (Vault %q in Resource Group %q): %+v", operationId, vaultName, resourceGroup, err)
}

return resp, "Pending", nil
return resp, strconv.Itoa(resp.StatusCode), err
},

Timeout: d.Timeout(pluginsdk.TimeoutDelete),
}

_, err = containerState.WaitForStateContext(ctx)
_, err = opState.WaitForStateContext(ctx)
if err != nil {
return resp.(backup.ProtectedItemResource), fmt.Errorf("waiting for the Azure Backup Protection Container %q to be deleted (Resource Group %q): %+v", containerName, resourceGroup, err)
return resp.(backup.ProtectedItemResource), fmt.Errorf("waiting for the Recovery Service Protected Item operation %q to be deleted (Resource Group %q): %+v", containerName, resourceGroup, err)
}

return resp.(backup.ProtectedItemResource), nil
Expand Down
5 changes: 5 additions & 0 deletions internal/services/recoveryservices/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Client struct {
ProtectionContainerOperationResultsClient *backup.ProtectionContainerOperationResultsClient
BackupProtectionContainersClient *backup.ProtectionContainersClient
BackupOperationStatusesClient *backup.OperationStatusesClient
BackupOperationResultsClient *backup.OperationResultsClient
VaultsClient *vaults.VaultsClient
VaultsConfigsClient *backupresourcevaultconfigs.BackupResourceVaultConfigsClient
StorageConfigsClient *backupresourcestorageconfigsnoncrr.BackupResourceStorageConfigsNonCRRClient
Expand Down Expand Up @@ -63,6 +64,9 @@ func NewClient(o *common.ClientOptions) *Client {
backupOperationStatusesClient := backup.NewOperationStatusesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&backupOperationStatusesClient.Client, o.ResourceManagerAuthorizer)

backupOperationResultClient := backup.NewOperationResultsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&backupOperationResultClient.Client, o.ResourceManagerAuthorizer)

backupProtectionContainerOperationResultsClient := backup.NewProtectionContainerOperationResultsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&backupProtectionContainerOperationResultsClient.Client, o.ResourceManagerAuthorizer)

Expand Down Expand Up @@ -95,6 +99,7 @@ func NewClient(o *common.ClientOptions) *Client {
ProtectionContainerOperationResultsClient: &backupProtectionContainerOperationResultsClient,
BackupProtectionContainersClient: &backupProtectionContainersClient,
BackupOperationStatusesClient: &backupOperationStatusesClient,
BackupOperationResultsClient: &backupOperationResultClient,
VaultsClient: &vaultsClient,
VaultsConfigsClient: &vaultConfigsClient,
StorageConfigsClient: &storageConfigsClient,
Expand Down

0 comments on commit 0b810d8

Please sign in to comment.