Skip to content

Commit da1d89a

Browse files
author
Zubair Abid
committed
Initial code changes
1 parent 617ddcf commit da1d89a

File tree

8 files changed

+135
-5
lines changed

8 files changed

+135
-5
lines changed

src/azure-cli/azure/cli/command_modules/backup/_client_factory.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ def vaults_cf(cli_ctx, *_):
5757
return _common_client_factory(cli_ctx).vaults
5858

5959

60+
def deleted_vaults_cf(cli_ctx, *_):
61+
return _common_client_factory(cli_ctx).deleted_vaults
62+
63+
6064
def registered_identities_cf(cli_ctx, *_):
6165
return _common_client_factory(cli_ctx).registered_identities
6266

src/azure-cli/azure/cli/command_modules/backup/_help.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,3 +597,38 @@
597597
- name: Delete resource guard mapping of the Recovery Services vault.
598598
text: az backup vault resource-guard-mapping delete --resource-group MyResourceGroup --name MyVault
599599
"""
600+
601+
helps['backup vault deleted-vault'] = """
602+
type: group
603+
short-summary: Manage soft-deleted Recovery Services vaults.
604+
"""
605+
606+
helps['backup vault deleted-vault list'] = """
607+
type: command
608+
short-summary: List soft-deleted Recovery Services vaults.
609+
examples:
610+
- name: List all soft-deleted vaults in the current subscription.
611+
text: az backup vault deleted-vault list
612+
- name: List soft-deleted vaults in a specific resource group.
613+
text: az backup vault deleted-vault list --resource-group MyResourceGroup
614+
- name: List soft-deleted vaults in a specific location.
615+
text: az backup vault deleted-vault list --location eastus
616+
"""
617+
618+
helps['backup vault deleted-vault undelete'] = """
619+
type: command
620+
short-summary: Restore a soft-deleted Recovery Services vault.
621+
examples:
622+
- name: Restore a soft-deleted vault by name and resource group.
623+
text: az backup vault deleted-vault undelete --name MyVault --resource-group MyResourceGroup --location eastus
624+
- name: Restore a soft-deleted vault using its ARM ID.
625+
text: az backup vault deleted-vault undelete --vault-id /subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/Microsoft.RecoveryServices/vaults/{vault-name}
626+
"""
627+
628+
helps['backup vault deleted-vault list-containers'] = """
629+
type: command
630+
short-summary: List backup containers in a soft-deleted vault.
631+
examples:
632+
- name: List backup containers in a soft-deleted vault.
633+
text: az backup vault deleted-vault list-containers --name MyVault --resource-group MyResourceGroup
634+
"""

src/azure-cli/azure/cli/command_modules/backup/commands.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# --------------------------------------------------------------------------------------------
55

66
from azure.cli.core.commands import CliCommandType
7-
from azure.cli.command_modules.backup._client_factory import vaults_cf, backup_protection_containers_cf, \
7+
from azure.cli.command_modules.backup._client_factory import vaults_cf, deleted_vaults_cf, backup_protection_containers_cf, \
88
protection_policies_cf, backup_policies_cf, protected_items_cf, backups_cf, backup_jobs_cf, \
99
job_details_cf, job_cancellations_cf, recovery_points_cf, restores_cf, backup_storage_configs_non_crr_cf, \
1010
item_level_recovery_connections_cf, backup_protected_items_cf, backup_protectable_items_cf, \
@@ -43,6 +43,11 @@ def load_command_table(self, _):
4343
g.custom_command('encryption update', 'update_encryption')
4444
g.custom_command('encryption show', 'show_encryption', client_factory=backup_resource_encryption_config_cf)
4545

46+
with self.command_group('backup vault deleted-vault', backup_custom, client_factory=deleted_vaults_cf, exception_handler=backup_exception_handler) as g:
47+
g.custom_command('list', 'list_deleted_vaults')
48+
g.custom_command('undelete', 'undelete_vault')
49+
g.custom_command('list-containers', 'list_deleted_vault_containers')
50+
4651
with self.command_group('backup vault resource-guard-mapping', backup_custom, client_factory=resource_guard_proxy_cf, exception_handler=backup_exception_handler) as g:
4752
g.show_command('update', 'update_resource_guard_mapping')
4853
g.show_command('show', 'show_resource_guard_mapping')

src/azure-cli/azure/cli/command_modules/backup/custom.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,92 @@ def list_vaults(client, resource_group_name=None):
449449
return client.list_by_subscription_id()
450450

451451

452+
def list_deleted_vaults(cmd, client, resource_group_name=None, location=None):
453+
"""List soft-deleted Recovery Services vaults."""
454+
subscription_id = get_subscription_id(cmd.cli_ctx)
455+
return client.list_by_subscription_id(subscription_id, location=location)
456+
457+
458+
def undelete_vault(cmd, client, vault_name, resource_group_name=None, location=None, vault_id=None):
459+
"""Restore a soft-deleted Recovery Services vault."""
460+
# Parse vault ID if provided
461+
if vault_id:
462+
if not is_valid_resource_id(vault_id):
463+
raise InvalidArgumentValueError("Invalid vault ID format.")
464+
465+
# Parse resource ID to extract subscription, resource group, and vault name
466+
vault_id_parts = vault_id.split('/')
467+
if len(vault_id_parts) < 9:
468+
raise InvalidArgumentValueError("Invalid vault ID format.")
469+
470+
parsed_subscription_id = vault_id_parts[2]
471+
parsed_resource_group = vault_id_parts[4]
472+
parsed_vault_name = vault_id_parts[8]
473+
474+
# Override parameters if vault_id is provided
475+
resource_group_name = parsed_resource_group
476+
vault_name = parsed_vault_name
477+
478+
# Validate subscription ID matches current context
479+
current_subscription_id = get_subscription_id(cmd.cli_ctx)
480+
if parsed_subscription_id != current_subscription_id:
481+
raise InvalidArgumentValueError(
482+
f"Vault ID subscription ({parsed_subscription_id}) does not match current subscription ({current_subscription_id})."
483+
)
484+
485+
if not vault_name or not resource_group_name:
486+
raise RequiredArgumentMissingError("Either provide vault-name and resource-group-name, or a valid vault-id.")
487+
488+
if not location:
489+
# If location not provided, try to get it from the deleted vault list
490+
subscription_id = get_subscription_id(cmd.cli_ctx)
491+
deleted_vaults = client.list_by_subscription_id(subscription_id)
492+
493+
for deleted_vault in deleted_vaults:
494+
if (deleted_vault.name == vault_name and
495+
deleted_vault.id and resource_group_name in deleted_vault.id):
496+
location = deleted_vault.location
497+
break
498+
499+
if not location:
500+
raise RequiredArgumentMissingError(
501+
"Location is required. Could not determine location from deleted vault list."
502+
)
503+
504+
return client.begin_undelete(resource_group_name, vault_name, location=location)
505+
506+
507+
def list_deleted_vault_containers(cmd, vault_name, resource_group_name):
508+
"""List backup containers in a soft-deleted vault using Azure Resource Graph."""
509+
from azure.mgmt.resourcegraph import ResourceGraphClient
510+
from azure.mgmt.resourcegraph.models import QueryRequest
511+
512+
subscription_id = get_subscription_id(cmd.cli_ctx)
513+
vault_resource_id = f"/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.RecoveryServices/vaults/{vault_name}"
514+
515+
# Create Resource Graph client
516+
resource_graph_client = get_mgmt_service_client(cmd.cli_ctx, ResourceGraphClient)
517+
518+
# Construct the query to find backup containers in the deleted vault
519+
query = f"""
520+
recoveryservicesresources
521+
| where type == "microsoft.recoveryservices/vaults/backupfabrics/protectioncontainers"
522+
| where id startswith "{vault_resource_id}"
523+
| project id, name, type, properties, location
524+
"""
525+
526+
query_request = QueryRequest(
527+
subscriptions=[subscription_id],
528+
query=query
529+
)
530+
531+
try:
532+
response = resource_graph_client.resources(query_request)
533+
return response.data
534+
except Exception as ex:
535+
raise CLIError(f"Failed to query backup containers: {str(ex)}")
536+
537+
452538
def assign_identity(client, resource_group_name, vault_name, system_assigned=None, user_assigned=None):
453539
vault_details = client.get(resource_group_name, vault_name)
454540

src/azure-cli/requirements.py3.Darwin.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ azure-mgmt-postgresqlflexibleservers==1.1.0b2
6060
azure-mgmt-privatedns==1.0.0
6161
azure-mgmt-rdbms==10.2.0b17
6262
azure-mgmt-mysqlflexibleservers==1.0.0b3
63-
azure-mgmt-recoveryservices==3.1.0
63+
azure-mgmt-recoveryservices==4.0.0
6464
azure-mgmt-recoveryservicesbackup==9.2.0
6565
azure-mgmt-redhatopenshift==1.5.0
6666
azure-mgmt-redis==14.5.0

src/azure-cli/requirements.py3.Linux.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ azure-mgmt-postgresqlflexibleservers==1.1.0b2
6060
azure-mgmt-privatedns==1.0.0
6161
azure-mgmt-rdbms==10.2.0b17
6262
azure-mgmt-mysqlflexibleservers==1.0.0b3
63-
azure-mgmt-recoveryservices==3.1.0
63+
azure-mgmt-recoveryservices==4.0.0
6464
azure-mgmt-recoveryservicesbackup==9.2.0
6565
azure-mgmt-redhatopenshift==1.5.0
6666
azure-mgmt-redis==14.5.0

src/azure-cli/requirements.py3.windows.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ azure-mgmt-postgresqlflexibleservers==1.1.0b2
6060
azure-mgmt-privatedns==1.0.0
6161
azure-mgmt-rdbms==10.2.0b17
6262
azure-mgmt-mysqlflexibleservers==1.0.0b3
63-
azure-mgmt-recoveryservices==3.1.0
63+
azure-mgmt-recoveryservices==4.0.0
6464
azure-mgmt-recoveryservicesbackup==9.2.0
6565
azure-mgmt-redhatopenshift==1.5.0
6666
azure-mgmt-redis==14.5.0

src/azure-cli/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@
105105
'azure-mgmt-rdbms==10.2.0b17',
106106
'azure-mgmt-mysqlflexibleservers==1.0.0b3',
107107
'azure-mgmt-recoveryservicesbackup~=9.2.0',
108-
'azure-mgmt-recoveryservices~=3.1.0',
108+
'azure-mgmt-recoveryservices~=4.0.0',
109109
'azure-mgmt-redhatopenshift~=1.5.0',
110110
'azure-mgmt-redis~=14.5.0',
111111
'azure-mgmt-resource==23.3.0',

0 commit comments

Comments
 (0)