Skip to content

Commit aa0680e

Browse files
authored
[RDBMS] az postgres flexible-server create/update: Show high availability feature with zonal resiliency argument (#32482)
1 parent 3082908 commit aa0680e

File tree

7 files changed

+1173
-1003
lines changed

7 files changed

+1173
-1003
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
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+
from azure.cli.core.breaking_change import register_argument_deprecate
7+
8+
register_argument_deprecate('postgres flexible-server create', '--high-availability', redirect='--zonal-resiliency')
9+
register_argument_deprecate('postgres flexible-server update', '--high-availability', redirect='--zonal-resiliency')

src/azure-cli/azure/cli/command_modules/rdbms/_helptext_pg.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,12 @@
4040
az postgres flexible-server create --location northeurope --resource-group testGroup \\
4141
--name testserver --admin-user username --admin-password password \\
4242
--sku-name Standard_D2s_v3 --tier GeneralPurpose --public-access 153.24.26.117 --storage-size 128 \\
43-
--tags "key=value" --version 17 --high-availability ZoneRedundant --zone 1 \\
43+
--tags "key=value" --version 17 --zonal-resiliency Enabled --zone 1 \\
4444
--standby-zone 3
45+
- name: >
46+
Create server with high availability feature enabled that allows primary and standby in the same zone when multi-zone capacity is unavailable.
47+
text: >
48+
az postgres flexible-server create -g testGroup -n testCluster --location testLocation --zonal-resiliency Enabled --allow-same-zone
4549
- name: >
4650
Create a PostgreSQL flexible server using Premium SSD v2 Disks.
4751
text: >

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,18 @@ def _flexible_server_params(command_group):
453453
help='Enable (ZoneRedundant or SameZone) or disable high availability feature.'
454454
)
455455

456+
zonal_resiliency_arg_type = CLIArgumentType(
457+
arg_type=get_enum_type(['Enabled', 'Disabled']),
458+
options_list=['--zonal-resiliency'],
459+
help='Enable or disable high availability feature.'
460+
)
461+
462+
allow_same_zone_arg_type = CLIArgumentType(
463+
options_list=['--allow-same-zone'],
464+
action='store_true',
465+
help='Allow primary and standby in the same zone when multi-zone capacity is unavailable.'
466+
)
467+
456468
mysql_version_upgrade_arg_type = CLIArgumentType(
457469
arg_type=get_enum_type(['8']),
458470
options_list=['--version', '-v'],
@@ -607,6 +619,8 @@ def _flexible_server_params(command_group):
607619
c.argument('performance_tier', default=None, arg_type=performance_tier_arg_type)
608620
c.argument('create_cluster', default='Server', arg_type=cluster_option_arg_type)
609621
c.argument('cluster_size', default=None, arg_type=create_node_count_arg_type)
622+
c.argument('zonal_resiliency', arg_type=zonal_resiliency_arg_type, default="Disabled")
623+
c.argument('allow_same_zone', arg_type=allow_same_zone_arg_type, default=False)
610624
elif command_group == 'mysql':
611625
c.argument('tier', default='Burstable', arg_type=tier_arg_type)
612626
c.argument('sku_name', default='Standard_B1ms', arg_type=sku_name_arg_type)
@@ -749,6 +763,8 @@ def _flexible_server_params(command_group):
749763
c.argument('password_auth', arg_type=password_auth_arg_type)
750764
c.argument('private_dns_zone_arguments', private_dns_zone_arguments_arg_type)
751765
c.argument('cluster_size', default=None, arg_type=update_node_count_arg_type)
766+
c.argument('zonal_resiliency', arg_type=zonal_resiliency_arg_type)
767+
c.argument('allow_same_zone', arg_type=allow_same_zone_arg_type)
752768
c.argument('yes', arg_type=yes_arg_type)
753769

754770
with self.argument_context('{} flexible-server upgrade'.format(command_group)) as c:

src/azure-cli/azure/cli/command_modules/rdbms/flexible_server_custom_postgres.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ def flexible_server_create(cmd, client,
6565
password_auth=None, administrator_login=None, administrator_login_password=None,
6666
tags=None, subnet=None, subnet_address_prefix=None, vnet=None, vnet_address_prefix=None,
6767
private_dns_zone_arguments=None, public_access=None,
68-
high_availability=None, zone=None, standby_availability_zone=None,
68+
high_availability=None, zonal_resiliency=None, allow_same_zone=False,
69+
zone=None, standby_availability_zone=None,
6970
geo_redundant_backup=None, byok_identity=None, byok_key=None, backup_byok_identity=None, backup_byok_key=None,
7071
auto_grow=None, performance_tier=None,
7172
storage_type=None, iops=None, throughput=None, create_cluster=None, cluster_size=None, yes=False):
@@ -85,8 +86,10 @@ def flexible_server_create(cmd, client,
8586
logging_name='PostgreSQL', command_group='postgres', server_client=client, location=location)
8687

8788
server_name = server_name.lower()
89+
high_availability_mode = high_availability
8890

89-
if (sku_name is None) or (version is None):
91+
if (sku_name is None) or (version is None) or \
92+
(zonal_resiliency is not None and zonal_resiliency.lower() != 'disabled'):
9093
list_location_capability_info = get_postgres_location_capability_info(cmd, location)
9194

9295
# set sku_name from capability API
@@ -103,6 +106,10 @@ def flexible_server_create(cmd, client,
103106
if version is None:
104107
supported_server_versions = sorted(list_location_capability_info['supported_server_versions'])
105108
version = supported_server_versions[-1]
109+
# set high availability from capability API
110+
if (zonal_resiliency is not None and zonal_resiliency.lower() != 'disabled'):
111+
single_az = list_location_capability_info['single_az']
112+
high_availability_mode = 'SameZone' if single_az and allow_same_zone else 'ZoneRedundant'
106113

107114
pg_arguments_validator(db_context,
108115
server_name=server_name,
@@ -113,6 +120,8 @@ def flexible_server_create(cmd, client,
113120
storage_type=storage_type,
114121
iops=iops, throughput=throughput,
115122
high_availability=high_availability,
123+
zonal_resiliency=zonal_resiliency,
124+
allow_same_zone=allow_same_zone,
116125
standby_availability_zone=standby_availability_zone,
117126
zone=zone,
118127
subnet=subnet,
@@ -155,7 +164,7 @@ def flexible_server_create(cmd, client,
155164

156165
sku = postgresql_flexibleservers.models.Sku(name=sku_name, tier=tier)
157166

158-
high_availability = postgresql_flexibleservers.models.HighAvailability(mode=high_availability,
167+
high_availability = postgresql_flexibleservers.models.HighAvailability(mode=high_availability_mode,
159168
standby_availability_zone=standby_availability_zone)
160169

161170
is_password_auth_enabled = bool(password_auth is not None and password_auth.lower() == 'enabled')
@@ -319,6 +328,8 @@ def flexible_server_update_custom_func(cmd, client, instance,
319328
backup_retention=None,
320329
administrator_login_password=None,
321330
high_availability=None,
331+
zonal_resiliency=None,
332+
allow_same_zone=False,
322333
standby_availability_zone=None,
323334
maintenance_window=None,
324335
byok_identity=None, byok_key=None,
@@ -349,6 +360,8 @@ def flexible_server_update_custom_func(cmd, client, instance,
349360
iops=iops,
350361
throughput=throughput,
351362
high_availability=high_availability,
363+
zonal_resiliency=zonal_resiliency,
364+
allow_same_zone=allow_same_zone,
352365
zone=instance.availability_zone,
353366
standby_availability_zone=standby_availability_zone,
354367
byok_identity=byok_identity,
@@ -464,6 +477,13 @@ def flexible_server_update_custom_func(cmd, client, instance,
464477

465478
# High availability can't be updated with existing properties
466479
high_availability_param = postgresql_flexibleservers.models.HighAvailability()
480+
if zonal_resiliency is not None:
481+
if zonal_resiliency.lower() == 'disabled':
482+
high_availability = 'Disabled'
483+
else:
484+
list_location_capability_info = get_postgres_location_capability_info(cmd, location)
485+
single_az = list_location_capability_info['single_az']
486+
high_availability = 'SameZone' if single_az and allow_same_zone else 'ZoneRedundant'
467487
if high_availability:
468488
high_availability_param.mode = high_availability
469489

src/azure-cli/azure/cli/command_modules/rdbms/tests/latest/recordings/test_postgres_flexible_server_mgmt.yaml

Lines changed: 1088 additions & 990 deletions
Large diffs are not rendered by default.

src/azure-cli/azure/cli/command_modules/rdbms/tests/latest/test_rdbms_flexible_commands.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,13 @@ def _test_flexible_server_mgmt(self, database_engine, resource_group):
142142
tier = 'GeneralPurpose'
143143
backup_retention = 7
144144
server_name = self.create_random_name(SERVER_NAME_PREFIX, SERVER_NAME_MAX_LENGTH)
145+
zonal_resiliency_value = 'Enabled'
145146
ha_value = 'ZoneRedundant'
146147

147148
self.cmd('{} flexible-server create -g {} -n {} --backup-retention {} --sku-name {} --tier {} \
148-
--storage-size {} -u {} --version {} --tags keys=3 --high-availability {} \
149+
--storage-size {} -u {} --version {} --tags keys=3 --zonal-resiliency {} \
149150
--public-access None'.format(database_engine, resource_group, server_name, backup_retention,
150-
sku_name, tier, storage_size, 'dbadmin', version, ha_value))
151+
sku_name, tier, storage_size, 'dbadmin', version, zonal_resiliency_value))
151152

152153
basic_info = self.cmd('{} flexible-server show -g {} -n {}'.format(database_engine, resource_group, server_name)).get_output_in_json()
153154
self.assertEqual(basic_info['name'], server_name)
@@ -158,6 +159,7 @@ def _test_flexible_server_mgmt(self, database_engine, resource_group):
158159
self.assertEqual(basic_info['version'], version)
159160
self.assertEqual(basic_info['storage']['storageSizeGb'], storage_size)
160161
self.assertEqual(basic_info['backup']['backupRetentionDays'], backup_retention)
162+
self.assertEqual(basic_info['highAvailability']['mode'], ha_value)
161163

162164
self.cmd('{} flexible-server db show -g {} -s {} -d {}'
163165
.format(database_engine, resource_group, server_name, db_name), checks=[JMESPathCheck('name', db_name)])

src/azure-cli/azure/cli/command_modules/rdbms/validators.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,8 @@ def _mysql_iops_validator(iops, auto_io_scaling, instance):
306306

307307

308308
def pg_arguments_validator(db_context, location, tier, sku_name, storage_gb, server_name=None, database_name=None,
309-
zone=None, standby_availability_zone=None, high_availability=None, subnet=None,
309+
zone=None, standby_availability_zone=None, high_availability=None,
310+
zonal_resiliency=None, allow_same_zone=False, subnet=None,
310311
public_access=None, version=None, instance=None, geo_redundant_backup=None,
311312
byok_identity=None, byok_key=None, backup_byok_identity=None, backup_byok_key=None,
312313
auto_grow=None, performance_tier=None,
@@ -349,7 +350,8 @@ def pg_arguments_validator(db_context, location, tier, sku_name, storage_gb, ser
349350
_pg_georedundant_backup_validator(geo_redundant_backup, geo_backup_supported)
350351
_pg_storage_validator(storage_gb, sku_info, tier, storage_type, iops, throughput, instance)
351352
_pg_sku_name_validator(sku_name, sku_info, tier, instance)
352-
_pg_high_availability_validator(high_availability, standby_availability_zone, zone, tier, single_az, instance)
353+
_pg_high_availability_validator(high_availability, zonal_resiliency, allow_same_zone,
354+
standby_availability_zone, zone, tier, single_az, instance)
353355
_pg_version_validator(version, list_location_capability_info['server_versions'])
354356
pg_byok_validator(byok_identity, byok_key, backup_byok_identity, backup_byok_key, geo_redundant_backup, instance)
355357
is_microsoft_entra_auth = bool(microsoft_entra_auth is not None and microsoft_entra_auth.lower() == 'enabled')
@@ -509,27 +511,46 @@ def _pg_version_validator(version, versions):
509511
"maintain security, performance, and supportability.")
510512

511513

512-
def _pg_high_availability_validator(high_availability, standby_availability_zone, zone, tier, single_az, instance):
514+
def _pg_high_availability_validator(high_availability, zonal_resiliency, allow_same_zone,
515+
standby_availability_zone, zone, tier, single_az, instance):
516+
high_availability_enabled = (high_availability is not None and high_availability.lower() != 'disabled')
517+
zonal_resiliency_enabled = (zonal_resiliency is not None and zonal_resiliency.lower() != 'disabled')
518+
high_availability_zone_redundant = (high_availability_enabled and high_availability.lower() == 'zoneredundant')
519+
520+
if high_availability_enabled and zonal_resiliency_enabled:
521+
raise ArgumentUsageError("Setting both --high-availability and --zonal-resiliency is not allowed. "
522+
"Please set only --zonal-resiliency to move forward.")
523+
513524
if instance:
514525
tier = instance.sku.tier if tier is None else tier
515526
zone = instance.availability_zone if zone is None else zone
516527

517-
if high_availability is not None and high_availability.lower() != 'disabled':
528+
if high_availability_enabled:
518529
if tier == 'Burstable':
519530
raise ArgumentUsageError("High availability is not supported for Burstable tier")
520-
if single_az and high_availability.lower() == 'zoneredundant':
531+
if single_az and high_availability_zone_redundant:
521532
raise ArgumentUsageError("This region is single availability zone. "
522533
"Zone redundant high availability is not supported "
523534
"in a single availability zone region.")
524535

536+
if zonal_resiliency_enabled:
537+
if tier == 'Burstable':
538+
raise ArgumentUsageError("High availability is not supported for Burstable tier")
539+
if single_az and allow_same_zone is False:
540+
raise ArgumentUsageError("This region is single availability zone. "
541+
"To proceed, please set --allow-same-zone.")
542+
525543
if standby_availability_zone:
526-
if not high_availability or high_availability.lower() != 'zoneredundant':
527-
raise ArgumentUsageError("You need to enable zone redundant high availability "
544+
if not high_availability_zone_redundant or not zonal_resiliency_enabled:
545+
raise ArgumentUsageError("You need to enable high availability by setting --zonal-resiliency to Enabled "
528546
"to set standby availability zone.")
529547
if zone == standby_availability_zone:
530548
raise ArgumentUsageError("Your server is in availability zone {}. "
531549
"The zone of the server cannot be same as the standby zone.".format(zone))
532550

551+
if allow_same_zone and not zonal_resiliency_enabled:
552+
raise ArgumentUsageError("You can only set --allow-same-zone when --zonal-resiliency is Enabled.")
553+
533554

534555
def _pg_georedundant_backup_validator(geo_redundant_backup, geo_backup_supported):
535556
if (geo_redundant_backup and geo_redundant_backup.lower() == 'enabled') and not geo_backup_supported:

0 commit comments

Comments
 (0)