Skip to content

Commit 2d05a0e

Browse files
authored
[Storage] az storage account: New features for 2025-08-01 (#33423)
1 parent 179ad99 commit 2d05a0e

7 files changed

Lines changed: 2182 additions & 254 deletions

File tree

src/azure-cli/azure/cli/command_modules/storage/_params.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,10 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
323323
c.argument('account_name', acct_name_type, options_list=['--name', '-n'], local_context_attribute=None)
324324

325325
with self.argument_context('storage account create', resource_type=ResourceType.MGMT_STORAGE) as c:
326-
t_account_type, t_sku_name, t_kind, t_tls_version, t_dns_endpoint_type, t_zone_placement_policy = \
327-
self.get_models('AccountType', 'SkuName', 'Kind', 'MinimumTlsVersion', 'DnsEndpointType',
328-
'ZonePlacementPolicy',
329-
resource_type=ResourceType.MGMT_STORAGE)
326+
(t_account_type, t_sku_name, t_kind, t_tls_version, t_dns_endpoint_type, t_zone_placement_policy,
327+
t_allowed_copy_scope) = self.get_models('AccountType', 'SkuName', 'Kind', 'MinimumTlsVersion',
328+
'DnsEndpointType', 'ZonePlacementPolicy', 'AllowedCopyScope',
329+
resource_type=ResourceType.MGMT_STORAGE)
330330
t_identity_type = self.get_models('IdentityType', resource_type=ResourceType.MGMT_STORAGE)
331331
c.register_common_storage_account_options()
332332
c.argument('location', get_location_type(self.cli_ctx), validator=get_default_location_from_resource_group)
@@ -447,6 +447,9 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
447447
c.argument('publish_ipv6_endpoint', arg_type=get_three_state_flag(),
448448
arg_group='IPv6 Endpoint', is_preview=True,
449449
help='A boolean flag which indicates whether IPv6 storage endpoints are to be published.')
450+
c.argument('allowed_copy_scope', arg_type=get_enum_type(t_allowed_copy_scope),
451+
help='Restrict copy to and from Storage Accounts within an AAD tenant or with Private Links to the '
452+
'same VNet.')
450453

451454
with self.argument_context('storage account private-endpoint-connection',
452455
resource_type=ResourceType.MGMT_STORAGE) as c:
@@ -550,6 +553,9 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
550553
c.argument('publish_ipv6_endpoint', arg_type=get_three_state_flag(),
551554
arg_group='IPv6 Endpoint', is_preview=True,
552555
help='A boolean flag which indicates whether IPv6 storage endpoints are to be published.')
556+
c.argument('allowed_copy_scope', arg_type=get_enum_type(t_allowed_copy_scope),
557+
help='Restrict copy to and from Storage Accounts within an AAD tenant or with Private Links to the '
558+
'same VNet.')
553559

554560
for scope in ['storage account create', 'storage account update']:
555561
with self.argument_context(scope, arg_group='Customer managed key',
@@ -726,6 +732,20 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
726732
c.argument('enable_last_access_tracking', arg_type=get_three_state_flag(),
727733
options_list=['--enable-last-access-tracking', '-t'],
728734
help='When set to true last access time based tracking policy is enabled.')
735+
c.argument('enable_static_website', arg_type=get_three_state_flag(), arg_group='Static Website',
736+
help='Indicates whether static website support is enabled for the specified account.')
737+
c.argument('index_document', arg_group='Static Website',
738+
help='The webpage that Azure Storage serves for requests to the root of a website or any subfolder '
739+
'(for example, index.html).')
740+
c.argument('default_index_document_path', arg_group='Static Website',
741+
options_list=['--default-index-document-path', '--default-index'],
742+
help='The absolute path where the default index file is present. This absolute path is mutually '
743+
'exclusive to "indexDocument" and it is case-sensitive.')
744+
c.argument('error_document_404_path', arg_group='Static Website',
745+
options_list=['--error-document-404-path', '--404-document'],
746+
help="The absolute path to a webpage that Azure Storage serves for requests that don't correspond "
747+
"to an existing file. The contents of the page are returned with HTTP 404 Not Found. "
748+
"Only a single custom 404 page is supported in each static website.")
729749

730750
with self.argument_context('storage account blob-service-properties cors-rule',
731751
resource_type=ResourceType.MGMT_STORAGE) as c:
@@ -838,6 +858,8 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
838858
help='Indicates whether object replication metrics feature is enabled for the policy.')
839859
c.argument('priority_replication', arg_type=get_three_state_flag(),
840860
help='Indicates whether object replication priority replication feature is enabled for the policy.')
861+
c.argument('tags_replication', arg_type=get_three_state_flag(),
862+
help='Indicates whether object replication tags replication feature is enabled for the policy.')
841863

842864
for item in ['create', 'update']:
843865
with self.argument_context('storage account or-policy {}'.format(item),

src/azure-cli/azure/cli/command_modules/storage/operations/account.py

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ def create_storage_account(cmd, resource_group_name, account_name, sku=None, loc
7979
immutability_period_since_creation_in_days=None, immutability_policy_state=None,
8080
allow_protected_append_writes=None, public_network_access=None, dns_endpoint_type=None,
8181
enable_smb_oauth=None, zones=None, zone_placement_policy=None,
82-
enable_blob_geo_priority_replication=None, publish_ipv6_endpoint=None):
82+
enable_blob_geo_priority_replication=None, publish_ipv6_endpoint=None,
83+
allowed_copy_scope=None):
8384
StorageAccountCreateParameters, Kind, Sku, CustomDomain, AccessTier, Identity, Encryption, NetworkRuleSet = \
8485
cmd.get_models('StorageAccountCreateParameters', 'Kind', 'Sku', 'CustomDomain', 'AccessTier', 'Identity',
8586
'Encryption', 'NetworkRuleSet')
@@ -334,6 +335,9 @@ def create_storage_account(cmd, resource_group_name, account_name, sku=None, loc
334335
publish_ipv6_endpoint=publish_ipv6_endpoint
335336
)
336337

338+
if allowed_copy_scope is not None:
339+
params.allowed_copy_scope = allowed_copy_scope
340+
337341
return scf.storage_accounts.begin_create(resource_group_name, account_name, params)
338342

339343

@@ -429,7 +433,8 @@ def update_storage_account(cmd, instance, sku=None, tags=None, custom_domain=Non
429433
immutability_period_since_creation_in_days=None, immutability_policy_state=None,
430434
allow_protected_append_writes=None, public_network_access=None, upgrade_to_storagev2=None,
431435
yes=None, enable_smb_oauth=None, zones=None, zone_placement_policy=None,
432-
enable_blob_geo_priority_replication=None, publish_ipv6_endpoint=None):
436+
enable_blob_geo_priority_replication=None, publish_ipv6_endpoint=None,
437+
allowed_copy_scope=None):
433438
StorageAccountUpdateParameters, Sku, CustomDomain, AccessTier, Identity, Encryption, NetworkRuleSet, Kind = \
434439
cmd.get_models('StorageAccountUpdateParameters', 'Sku', 'CustomDomain', 'AccessTier', 'Identity', 'Encryption',
435440
'NetworkRuleSet', 'Kind')
@@ -753,6 +758,9 @@ def update_storage_account(cmd, instance, sku=None, tags=None, custom_domain=Non
753758
publish_ipv6_endpoint=publish_ipv6_endpoint
754759
)
755760

761+
if allowed_copy_scope is not None:
762+
params.allowed_copy_scope = allowed_copy_scope
763+
756764
return params
757765

758766

@@ -924,7 +932,8 @@ def update_blob_service_properties(cmd, instance, enable_change_feed=None, chang
924932
enable_restore_policy=None, restore_days=None,
925933
enable_versioning=None, enable_container_delete_retention=None,
926934
container_delete_retention_days=None, default_service_version=None,
927-
enable_last_access_tracking=None):
935+
enable_last_access_tracking=None, enable_static_website=None,
936+
index_document=None, default_index_document_path=None, error_document_404_path=None):
928937
if enable_change_feed is not None:
929938
if enable_change_feed is False:
930939
change_feed_retention_days = None
@@ -960,6 +969,27 @@ def update_blob_service_properties(cmd, instance, enable_change_feed=None, chang
960969
LastAccessTimeTrackingPolicy = cmd.get_models('LastAccessTimeTrackingPolicy')
961970
instance.last_access_time_tracking_policy = LastAccessTimeTrackingPolicy(enable=enable_last_access_tracking)
962971

972+
if enable_static_website is not None or index_document or default_index_document_path or error_document_404_path:
973+
StaticWebsite = cmd.get_models('StaticWebsite')
974+
if enable_static_website is not None and not enable_static_website:
975+
instance.static_website = StaticWebsite(enabled=enable_static_website)
976+
else:
977+
if instance.static_website is None:
978+
instance.static_website = StaticWebsite(enabled=enable_static_website,
979+
index_document=index_document,
980+
default_index_document_path=default_index_document_path,
981+
error_document404_path=error_document_404_path)
982+
else:
983+
static_website = instance.static_website
984+
instance.static_website = StaticWebsite(
985+
enabled=(enable_static_website if enable_static_website is not None else static_website.enabled),
986+
index_document=(index_document if index_document else static_website.index_document),
987+
default_index_document_path=(
988+
default_index_document_path if default_index_document_path else
989+
static_website.default_index_document_path),
990+
error_document404_path=(
991+
error_document_404_path if error_document_404_path else static_website.error_document404_path))
992+
963993
return instance
964994

965995

@@ -1079,13 +1109,15 @@ def list_encryption_scope(client, resource_group_name, account_name,
10791109
def create_or_policy(cmd, client, account_name, resource_group_name=None, properties=None, source_account=None,
10801110
destination_account=None, policy_id="default", rule_id=None, source_container=None,
10811111
destination_container=None, min_creation_time=None, prefix_match=None, enable_metrics=None,
1082-
priority_replication=None):
1112+
priority_replication=None, tags_replication=None):
10831113
from azure.core.exceptions import HttpResponseError
10841114
(ObjectReplicationPolicy, ObjectReplicationPolicyRule, ObjectReplicationPolicyFilter,
1085-
ObjectReplicationPolicyPropertiesMetrics, ObjectReplicationPolicyPropertiesPriorityReplication) = \
1115+
ObjectReplicationPolicyPropertiesMetrics, ObjectReplicationPolicyPropertiesPriorityReplication,
1116+
ObjectReplicationPolicyPropertiesTagsReplication) = \
10861117
cmd.get_models('ObjectReplicationPolicy', 'ObjectReplicationPolicyRule', 'ObjectReplicationPolicyFilter',
10871118
'ObjectReplicationPolicyPropertiesMetrics',
1088-
'ObjectReplicationPolicyPropertiesPriorityReplication')
1119+
'ObjectReplicationPolicyPropertiesPriorityReplication',
1120+
'ObjectReplicationPolicyPropertiesTagsReplication')
10891121

10901122
if properties is None:
10911123
rules = []
@@ -1102,7 +1134,9 @@ def create_or_policy(cmd, client, account_name, resource_group_name=None, proper
11021134
rules=rules,
11031135
metrics=ObjectReplicationPolicyPropertiesMetrics(enabled=enable_metrics),
11041136
priority_replication=ObjectReplicationPolicyPropertiesPriorityReplication(
1105-
enabled=priority_replication))
1137+
enabled=priority_replication),
1138+
tags_replication=ObjectReplicationPolicyPropertiesTagsReplication(
1139+
enabled=tags_replication))
11061140
else:
11071141
rules = []
11081142
if properties.get('rules'):
@@ -1114,12 +1148,19 @@ def create_or_policy(cmd, client, account_name, resource_group_name=None, proper
11141148
min_creation_time=rule.get('filters').get(
11151149
'minCreationTime')) if rule.get('filters') else None
11161150
) for rule in properties['rules']]
1151+
11171152
or_policy = ObjectReplicationPolicy(source_account=properties.get('sourceAccount'),
11181153
destination_account=properties.get('destinationAccount'),
11191154
rules=rules,
1120-
metrics=ObjectReplicationPolicyPropertiesMetrics(enabled=properties.get('metrics').get('enabled')),
1155+
metrics=ObjectReplicationPolicyPropertiesMetrics(
1156+
enabled=properties.get('metrics').get('enabled')) if properties.get(
1157+
'metrics') else None,
11211158
priority_replication=ObjectReplicationPolicyPropertiesPriorityReplication(
1122-
enabled=properties.get('priorityReplication').get('enabled')))
1159+
enabled=properties.get('priorityReplication').get(
1160+
'enabled')) if properties.get('priorityReplication') else None,
1161+
tags_replication=ObjectReplicationPolicyPropertiesTagsReplication(
1162+
enabled=properties.get('tagsReplication').get(
1163+
'enabled')) if properties.get('tagsReplication') else None)
11231164
try:
11241165
return client.create_or_update(resource_group_name=resource_group_name, account_name=account_name,
11251166
object_replication_policy_id=policy_id, properties=or_policy)
@@ -1135,12 +1176,14 @@ def create_or_policy(cmd, client, account_name, resource_group_name=None, proper
11351176
# pylint: disable=line-too-long
11361177
def update_or_policy(cmd, client, parameters, resource_group_name, account_name, object_replication_policy_id=None,
11371178
properties=None, source_account=None, destination_account=None, enable_metrics=None,
1138-
priority_replication=None):
1179+
priority_replication=None, tags_replication=None):
11391180
(ObjectReplicationPolicy, ObjectReplicationPolicyRule, ObjectReplicationPolicyFilter,
1140-
ObjectReplicationPolicyPropertiesMetrics, ObjectReplicationPolicyPropertiesPriorityReplication) = \
1181+
ObjectReplicationPolicyPropertiesMetrics, ObjectReplicationPolicyPropertiesPriorityReplication,
1182+
ObjectReplicationPolicyPropertiesTagsReplication) = \
11411183
cmd.get_models('ObjectReplicationPolicy', 'ObjectReplicationPolicyRule', 'ObjectReplicationPolicyFilter',
11421184
'ObjectReplicationPolicyPropertiesMetrics',
1143-
'ObjectReplicationPolicyPropertiesPriorityReplication')
1185+
'ObjectReplicationPolicyPropertiesPriorityReplication',
1186+
'ObjectReplicationPolicyPropertiesTagsReplication')
11441187

11451188
if source_account is not None:
11461189
parameters.source_account = source_account
@@ -1162,17 +1205,26 @@ def update_or_policy(cmd, client, parameters, resource_group_name, account_name,
11621205
destination_account=properties.get('destinationAccount'),
11631206
rules=rules,
11641207
metrics=ObjectReplicationPolicyPropertiesMetrics(
1165-
enabled=properties.get('metrics').get('enabled')),
1208+
enabled=properties.get('metrics').get('enabled')) if properties.get(
1209+
'metrics') else None,
11661210
priority_replication=ObjectReplicationPolicyPropertiesPriorityReplication(
1167-
enabled=properties.get('priorityReplication').get('enabled')))
1211+
enabled=properties.get('priorityReplication').get(
1212+
'enabled')) if properties.get('priorityReplication') else None,
1213+
tags_replication=ObjectReplicationPolicyPropertiesTagsReplication(
1214+
enabled=properties.get('tagsReplication').get(
1215+
'enabled')) if properties.get('tagsReplication') else None)
11681216
if "policyId" in properties.keys() and properties["policyId"]:
11691217
object_replication_policy_id = properties["policyId"]
11701218

11711219
if enable_metrics is not None:
11721220
parameters.metrics = ObjectReplicationPolicyPropertiesMetrics(enabled=enable_metrics)
11731221

11741222
if priority_replication is not None:
1175-
parameters.priority_replication = ObjectReplicationPolicyPropertiesPriorityReplication(enabled=priority_replication)
1223+
parameters.priority_replication = ObjectReplicationPolicyPropertiesPriorityReplication(
1224+
enabled=priority_replication)
1225+
1226+
if tags_replication is not None:
1227+
parameters.tags_replication = ObjectReplicationPolicyPropertiesTagsReplication(enabled=tags_replication)
11761228

11771229
return client.create_or_update(resource_group_name=resource_group_name, account_name=account_name,
11781230
object_replication_policy_id=object_replication_policy_id, properties=parameters)

0 commit comments

Comments
 (0)