Skip to content

Commit 3fe1251

Browse files
committed
[SQL] Add short-term backup retention immutability support
1 parent cc010d2 commit 3fe1251

6 files changed

Lines changed: 601 additions & 117 deletions

File tree

‎src/azure-cli/azure/cli/command_modules/sql/_help.py‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,17 +214,23 @@
214214
helps['sql db str-policy set'] = """
215215
type: command
216216
short-summary: Update short term retention settings for a live database.
217+
long-summary: Locking backup immutability is irreversible. Confirmation is required only when --lock-immutability is true. Use --yes to skip confirmation. Specify at least one retention setting or --lock-immutability.
217218
examples:
218219
- name: Set short term retention for a live database.
219-
text: az sql db str-policy set -g mygroup -s myserver -n mydb --retention-days retentionindays --diffbackup-hours diffbackuphours
220+
text: az sql db str-policy set --resource-group mygroup --server myserver --name mydb --retention-days 7 --diffbackup-hours 24
221+
- name: Lock backup immutability without changing the retention settings, skipping confirmation.
222+
text: az sql db str-policy set --resource-group mygroup --server myserver --name mydb --lock-immutability true --yes
220223
"""
221224

222225
helps['sql db str-policy show'] = """
223226
type: command
224227
short-summary: Show the short term retention policy for a live database.
228+
long-summary: The immutabilityStatus output property reports Disabled, Enabled or Locked when returned by the service.
225229
examples:
226230
- name: Show short term retention policy for a live database.
227231
text: az sql db str-policy show -g mygroup -s myserver -n mydb
232+
- name: Show the current backup immutability status.
233+
text: az sql db str-policy show --resource-group mygroup --server myserver --name mydb --query immutabilityStatus
228234
"""
229235

230236
helps['sql db str-policy wait'] = """
@@ -1212,16 +1218,20 @@
12121218
helps['sql midb short-term-retention-policy set'] = """
12131219
type: command
12141220
short-summary: Update short term retention for automated backups on a single database.
1221+
long-summary: Locking backup immutability is irreversible and is supported only for live managed databases. Confirmation is required only when --lock-immutability is true; use --yes to skip it. Do not specify --lock-immutability with --deleted-time, even when false. Retention cannot be reduced on a dropped database whose backup immutability is locked.
12151222
examples:
12161223
- name: Set backup short term retention for live managed database.
1217-
text: az sql midb short-term-retention-policy set -g mygroup --mi myinstance -n mymanageddb --retention-days retentionindays
1224+
text: az sql midb short-term-retention-policy set -g mygroup --mi myinstance -n mymanageddb --retention-days 7
12181225
- name: Set backup short term retention for dropped managed database.
1219-
text: az sql midb short-term-retention-policy set -g mygroup --mi myinstance -n mymanageddb --deleted-time "2018-05-20T05:34:22" --retention-days retentionindays
1226+
text: az sql midb short-term-retention-policy set -g mygroup --mi myinstance -n mymanageddb --deleted-time "2018-05-20T05:34:22" --retention-days 7
1227+
- name: Lock backup immutability for a live managed database, skipping confirmation.
1228+
text: az sql midb short-term-retention-policy set --resource-group mygroup --mi myinstance --name mymanageddb --retention-days 7 --lock-immutability true --yes
12201229
"""
12211230

12221231
helps['sql midb short-term-retention-policy show'] = """
12231232
type: command
12241233
short-summary: Show short term retention for automated backups on a single database.
1234+
long-summary: The immutabilityStatus output property reports Disabled, Enabled or Locked for live and restorable dropped managed databases when returned by the service.
12251235
examples:
12261236
- name: Shows backup short term retention for live managed database.
12271237
text: az sql midb short-term-retention-policy show -g mygroup --mi myinstance -n mymanageddb

‎src/azure-cli/azure/cli/command_modules/sql/_params.py‎

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,24 +1506,29 @@ def _configure_security_policy_storage_params(arg_ctx):
15061506
# sql db str #
15071507
###############################################
15081508
with self.argument_context('sql db str-policy set') as c:
1509-
create_args_for_complex_type(
1510-
c, 'parameters', Database, [
1511-
'retention_days',
1512-
'diffbackup_hours'
1513-
])
1514-
15151509
c.argument(
15161510
'retention_days',
15171511
options_list=['--retention-days'],
1518-
required=True,
1512+
type=int,
1513+
required=False,
15191514
help='New backup short term retention policy retention in days.'
15201515
'Valid retention days for live database of (DTU) Basic can be 1-7 days; Rest models can be 1-35 days.')
1521-
15221516
c.argument(
15231517
'diffbackup_hours',
15241518
options_list=['--diffbackup-hours'],
1519+
type=int,
15251520
help='New backup short term retention policy differential backup interval in hours.'
15261521
'Valid differential backup interval for live database can be 12 or 24 hours.')
1522+
c.argument(
1523+
'lock_immutability',
1524+
arg_type=get_three_state_flag(),
1525+
help='Whether to lock backup immutability. Locking is irreversible. '
1526+
'Setting false does not unlock an already locked policy.')
1527+
c.argument(
1528+
'yes',
1529+
options_list=['--yes', '-y'],
1530+
action='store_true',
1531+
help='Do not prompt for confirmation when locking backup immutability.')
15271532

15281533
###############################################
15291534
# sql dw #
@@ -2825,24 +2830,28 @@ class ContainerIdentityType(Enum):
28252830
help='The id of recoverable database from geo-replicated instance')
28262831

28272832
with self.argument_context('sql midb short-term-retention-policy set') as c:
2828-
create_args_for_complex_type(
2829-
c, 'parameters', ManagedDatabase, [
2830-
'deleted_time',
2831-
'retention_days'
2832-
])
2833-
28342833
c.argument(
28352834
'deleted_time',
28362835
options_list=['--deleted-time'],
2837-
help='If specified, updates retention days for a deleted database, instead of an existing database.'
2838-
'Must match the deleted time of a deleted database on the source Managed Instance.')
2839-
2836+
help='If specified, updates retention days for a deleted database, instead of an existing database. '
2837+
'Must match the deleted time of a deleted database on the source Managed Instance.')
28402838
c.argument(
28412839
'retention_days',
28422840
options_list=['--retention-days'],
2841+
type=int,
28432842
required=True,
2844-
help='New backup short term retention policy in days.'
2845-
'Valid policy for live database is 7-35 days, valid policy for dropped databases is 0-35 days.')
2843+
help='New backup short term retention policy in days. '
2844+
'Valid policy for live database is 7-35 days, valid policy for dropped databases is 0-35 days.')
2845+
c.argument(
2846+
'lock_immutability',
2847+
arg_type=get_three_state_flag(),
2848+
help='Whether to lock backup immutability for a live managed database. '
2849+
'Locking is irreversible. Cannot be used with --deleted-time, even when false.')
2850+
c.argument(
2851+
'yes',
2852+
options_list=['--yes', '-y'],
2853+
action='store_true',
2854+
help='Do not prompt for confirmation when locking backup immutability.')
28462855

28472856
with self.argument_context('sql midb short-term-retention-policy show') as c:
28482857
c.argument(
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# --------------------------------------------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License. See License.txt in the project root for license information.
4+
# --------------------------------------------------------------------------------------------
5+
6+
"""SDK-independent STR operations shared by the existing SQL command handlers."""
7+
8+
from azure.cli.core.aaz import (
9+
AAZBoolArg, AAZBoolType, AAZCommand, AAZHttpOperation, AAZIntArg,
10+
AAZIntType, AAZObjectType, AAZStrArg, AAZStrType,
11+
)
12+
13+
14+
class _ShortTermRetentionPolicy(AAZCommand):
15+
def _handler(self, command_args):
16+
# None means omitted in the existing Python handlers, not an explicit JSON null.
17+
super()._handler({key: value for key, value in command_args.items() if value is not None})
18+
19+
@classmethod
20+
def _build_arguments_schema(cls, *args, **kwargs):
21+
schema = super()._build_arguments_schema(*args, **kwargs)
22+
schema.resource_group_name = AAZStrArg(required=True)
23+
schema.parent_name = AAZStrArg(required=True)
24+
schema.database_name = AAZStrArg(required=True)
25+
schema.managed = AAZBoolArg(default=False)
26+
schema.deleted = AAZBoolArg(default=False)
27+
schema.retention_days = AAZIntArg()
28+
schema.diffbackup_hours = AAZIntArg()
29+
schema.lock_immutability = AAZBoolArg()
30+
return schema
31+
32+
def _output(self, _result=None):
33+
return self.deserialize_output(self.ctx.vars.instance, client_flatten=True)
34+
35+
36+
class ShortTermRetentionPolicyGet(_ShortTermRetentionPolicy):
37+
def _handler(self, command_args):
38+
super()._handler(command_args)
39+
_PolicyGet(ctx=self.ctx)()
40+
return self._output()
41+
42+
43+
class ShortTermRetentionPolicySet(_ShortTermRetentionPolicy):
44+
AZ_SUPPORT_NO_WAIT = True
45+
46+
def _handler(self, command_args):
47+
super()._handler(command_args)
48+
return self.build_lro_poller(self._execute_operations, self._output)
49+
50+
def _execute_operations(self):
51+
yield _PolicySet(ctx=self.ctx)()
52+
53+
54+
class _PolicyOperation(AAZHttpOperation): # pylint: disable=abstract-method
55+
CLIENT_TYPE = "MgmtClient"
56+
57+
@property
58+
def url(self):
59+
parent_type = "managedInstances" if self.ctx.args.managed else "servers"
60+
child_type = "restorableDroppedDatabases" if self.ctx.args.deleted else "databases"
61+
return self.client.format_url(
62+
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}"
63+
"/providers/Microsoft.Sql/" + parent_type + "/{parentName}/" + child_type +
64+
"/{databaseName}/backupShortTermRetentionPolicies/default",
65+
**self.url_parameters
66+
)
67+
68+
@property
69+
def url_parameters(self):
70+
return {
71+
**self.serialize_url_param("subscriptionId", self.ctx.subscription_id, required=True),
72+
**self.serialize_url_param("resourceGroupName", self.ctx.args.resource_group_name, required=True),
73+
**self.serialize_url_param("parentName", self.ctx.args.parent_name, required=True),
74+
**self.serialize_url_param("databaseName", self.ctx.args.database_name, required=True),
75+
}
76+
77+
@property
78+
def query_parameters(self):
79+
return {"api-version": "2026-08-01-preview"}
80+
81+
@property
82+
def header_parameters(self):
83+
return {"Accept": "application/json", "Content-Type": "application/json"}
84+
85+
@property
86+
def error_format(self):
87+
return "ODataV4Format"
88+
89+
def on_success(self, session):
90+
self.ctx.set_var(
91+
"instance", self.deserialize_http_content(session),
92+
schema_builder=self._build_response_schema,
93+
)
94+
95+
@staticmethod
96+
def _build_response_schema():
97+
schema = AAZObjectType()
98+
schema.id = AAZStrType(flags={"read_only": True})
99+
schema.name = AAZStrType(flags={"read_only": True})
100+
schema.type = AAZStrType(flags={"read_only": True})
101+
schema.properties = AAZObjectType(flags={"client_flatten": True})
102+
properties = schema.properties
103+
properties.retention_days = AAZIntType(serialized_name="retentionDays")
104+
properties.diff_backup_interval_in_hours = AAZIntType(serialized_name="diffBackupIntervalInHours")
105+
properties.lock_immutability = AAZBoolType(serialized_name="lockImmutability")
106+
properties.immutability_status = AAZStrType(
107+
serialized_name="immutabilityStatus", flags={"read_only": True},
108+
)
109+
schema.system_data = AAZObjectType(serialized_name="systemData", flags={"read_only": True})
110+
system_data = schema.system_data
111+
system_data.created_by = AAZStrType(serialized_name="createdBy")
112+
system_data.created_by_type = AAZStrType(serialized_name="createdByType")
113+
system_data.created_at = AAZStrType(serialized_name="createdAt")
114+
system_data.last_modified_by = AAZStrType(serialized_name="lastModifiedBy")
115+
system_data.last_modified_by_type = AAZStrType(serialized_name="lastModifiedByType")
116+
system_data.last_modified_at = AAZStrType(serialized_name="lastModifiedAt")
117+
return schema
118+
119+
120+
class _PolicyGet(_PolicyOperation):
121+
@property
122+
def method(self):
123+
return "GET"
124+
125+
def __call__(self, *args, **kwargs):
126+
session = self.client.send_request(request=self.make_request(), stream=False, **kwargs)
127+
if session.http_response.status_code == 200:
128+
return self.on_success(session)
129+
return self.on_error(session.http_response)
130+
131+
132+
class _PolicySet(_PolicyOperation):
133+
@property
134+
def method(self):
135+
return "PUT"
136+
137+
@property
138+
def content(self):
139+
value, builder = self.new_content_builder(self.ctx.args, typ=AAZObjectType)
140+
builder.set_prop("properties", AAZObjectType)
141+
properties = builder.get(".properties")
142+
properties.set_prop("retentionDays", AAZIntType, ".retention_days")
143+
if not self.ctx.args.managed:
144+
properties.set_prop("diffBackupIntervalInHours", AAZIntType, ".diffbackup_hours")
145+
if not self.ctx.args.deleted:
146+
properties.set_prop("lockImmutability", AAZBoolType, ".lock_immutability")
147+
return self.serialize_content(value)
148+
149+
def __call__(self, *args, **kwargs):
150+
session = self.client.send_request(request=self.make_request(), stream=False, **kwargs)
151+
if session.http_response.status_code in (200, 202):
152+
return self.client.build_lro_polling(
153+
self.ctx.args.no_wait, session, self.on_success, self.on_error,
154+
lro_options={"final-state-via": "location"},
155+
path_format_arguments=self.url_parameters,
156+
)
157+
return self.on_error(session.http_response)

‎src/azure-cli/azure/cli/command_modules/sql/commands.py‎

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
)
2727

2828
from ._util import (
29-
get_sql_backup_short_term_retention_policies_operations,
3029
get_sql_server_azure_ad_administrators_operations,
3130
get_sql_capabilities_operations,
3231
get_sql_databases_operations,
@@ -55,7 +54,6 @@
5554
get_sql_recoverable_managed_databases_operations,
5655
get_sql_managed_database_advanced_threat_protection_settings_operations,
5756
get_sql_managed_database_restore_details_operations,
58-
get_sql_managed_backup_short_term_retention_policies_operations,
5957
get_sql_managed_database_long_term_retention_policies_operations,
6058
get_sql_managed_database_long_term_retention_backups_operations,
6159
get_sql_managed_instance_advanced_threat_protection_settings_operations,
@@ -384,17 +382,11 @@ def load_command_table(self, _):
384382
'restore',
385383
'restore_geo_backup')
386384

387-
backup_short_term_retention_policies_operations = CliCommandType(
388-
operations_tmpl='azure.mgmt.sql.operations#BackupShortTermRetentionPoliciesOperations.{}',
389-
client_factory=get_sql_backup_short_term_retention_policies_operations)
390-
391-
with self.command_group('sql db str-policy',
392-
backup_short_term_retention_policies_operations,
393-
client_factory=get_sql_backup_short_term_retention_policies_operations) as g:
385+
with self.command_group('sql db str-policy') as g:
394386

395387
g.custom_command('set', 'update_short_term_retention', supports_no_wait=True)
396388
g.custom_show_command('show', 'get_short_term_retention')
397-
g.wait_command('wait')
389+
g.custom_wait_command('wait', 'get_short_term_retention')
398390

399391
database_sensitivity_labels_operations = CliCommandType(
400392
operations_tmpl='azure.mgmt.sql.operations#SensitivityLabelsOperations.{}',
@@ -951,13 +943,7 @@ def load_command_table(self, _):
951943
setter_type=managed_database_advanced_threat_protection_setting_update_sdk,
952944
custom_func_name='midb_advanced_threat_protection_setting_update')
953945

954-
managed_backup_short_term_retention_policies_operations = CliCommandType(
955-
operations_tmpl='azure.mgmt.sql.operations#ManagedBackupShortTermRetentionPoliciesOperations.{}',
956-
client_factory=get_sql_managed_backup_short_term_retention_policies_operations)
957-
958-
with self.command_group('sql midb short-term-retention-policy',
959-
managed_backup_short_term_retention_policies_operations,
960-
client_factory=get_sql_managed_backup_short_term_retention_policies_operations) as g:
946+
with self.command_group('sql midb short-term-retention-policy') as g:
961947

962948
g.custom_command(
963949
'set',

0 commit comments

Comments
 (0)