Skip to content

Commit ebd682b

Browse files
[PostgreSQL] BREAKING CHANGE: az postgres flexible-server create/update: Remove deprecated --cluster-option and update validation logic (#33244)
1 parent da3f5dc commit ebd682b

7 files changed

Lines changed: 1168 additions & 443 deletions

File tree

src/azure-cli/azure/cli/command_modules/postgresql/_breaking_change.py

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

66
from azure.cli.core.breaking_change import (
7-
NextBreakingChangeWindow,
87
register_argument_deprecate,
98
register_command_group_deprecate,
109
register_other_breaking_change
@@ -105,12 +104,3 @@ def _register_network_resource_breaking_change(command_name):
105104

106105
# Replica command argument changes
107106
register_argument_deprecate('postgres flexible-server replica create', '--replica-name', redirect='--name')
108-
109-
# Elastic cluster command argument deprecated and will be removed in the future. Today,
110-
# users must specify both --cluster-option ElasticCluster and --node-count to create an
111-
# elastic cluster. In the future, providing --node-count alone will imply an elastic cluster.
112-
register_argument_deprecate(command='postgres flexible-server create', argument='--cluster-option',
113-
message='Currently, to create an elastic cluster you must specify '
114-
'--cluster-option ElasticCluster together with --node-count. In the '
115-
'future, providing --node-count alone will imply an elastic cluster.',
116-
target_version=NextBreakingChangeWindow())

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,9 @@
232232
az postgres flexible-server create -g testGroup -n testServer --location testLocation --storage-auto-grow Enabled
233233
234234
- name: >
235-
Create elastic cluster with node count of 5. Default node count is 2 when --cluster-option is "ElasticCluster".
235+
Create elastic cluster with node count of 5.
236236
text: >
237-
az postgres flexible-server create -g testGroup -n testCluster --location testLocation --cluster-option ElasticCluster --node-count 5
237+
az postgres flexible-server create -g testGroup -n testCluster --location testLocation --node-count 5
238238
"""
239239

240240
helps['postgres flexible-server show'] = """
@@ -293,7 +293,7 @@
293293
text: az postgres flexible-server update --resource-group testGroup --name testserver --iops 3000
294294
- name: Update a flexible server's storage to set Throughput (MB/sec). Server must be using Premium SSD v2 Disks.
295295
text: az postgres flexible-server update --resource-group testGroup --name testserver --throughput 125
296-
- name: Update a flexible server's cluster size by scaling up node count. Must be an Elastic Cluster.
296+
- name: Update a flexible server's cluster size by scaling up node count. Must be an elastic cluster.
297297
text: az postgres flexible-server update --resource-group testGroup --name testcluster --node-count 6
298298
"""
299299

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

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def _flexible_server_params(command_group):
9797
database_name_arg_type_cluster = CLIArgumentType(
9898
metavar='NAME',
9999
options_list=['--database-name', '-d'],
100-
help='The default database name for an elastic cluster. Only applicable when --cluster-option is set to ElasticCluster.',
100+
help='The default database name for an elastic cluster. Only applicable when --node-count is present.',
101101
local_context_attribute=LocalContextAttribute(
102102
name='database_name',
103103
actions=[LocalContextAction.GET, LocalContextAction.SET],
@@ -146,17 +146,10 @@ def _flexible_server_params(command_group):
146146
'This value can only be updated if flexible server is using Premium SSD v2 Disks.'
147147
)
148148

149-
cluster_option_arg_type = CLIArgumentType(
150-
arg_type=get_enum_type(['Server', 'ElasticCluster']),
151-
options_list=['--cluster-option'],
152-
help='Cluster option for the server. Servers are for workloads that can fit on one node. '
153-
'Elastic clusters provides schema- and row-based sharding on a database. Default value is Server.'
154-
)
155-
156149
create_node_count_arg_type = CLIArgumentType(
157150
type=int,
158151
options_list=['--node-count'],
159-
help='The number of nodes for elastic cluster. Default is 2 nodes.'
152+
help='The number of nodes for elastic cluster.'
160153
)
161154

162155
update_node_count_arg_type = CLIArgumentType(
@@ -407,7 +400,6 @@ def _flexible_server_params(command_group):
407400
c.argument('iops', default=None, arg_type=iops_v2_arg_type)
408401
c.argument('throughput', default=None, arg_type=throughput_arg_type)
409402
c.argument('performance_tier', default=None, arg_type=performance_tier_arg_type)
410-
c.argument('create_cluster', default='Server', arg_type=cluster_option_arg_type)
411403
c.argument('cluster_size', default=None, arg_type=create_node_count_arg_type)
412404
c.argument('zonal_resiliency', arg_type=zonal_resiliency_arg_type, default="Disabled")
413405
c.argument('allow_same_zone', arg_type=allow_same_zone_arg_type, default=False)

src/azure-cli/azure/cli/command_modules/postgresql/commands/custom_commands.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def flexible_server_create(cmd, client,
7878
zone=None, standby_availability_zone=None,
7979
geo_redundant_backup=None, byok_identity=None, byok_key=None, backup_byok_identity=None, backup_byok_key=None,
8080
auto_grow=None, performance_tier=None,
81-
storage_type=None, iops=None, throughput=None, create_cluster=None, cluster_size=None, database_name=None, yes=False):
81+
storage_type=None, iops=None, throughput=None, cluster_size=None, database_name=None, yes=False):
8282

8383
if not check_resource_group(resource_group_name):
8484
resource_group_name = None
@@ -141,13 +141,11 @@ def flexible_server_create(cmd, client,
141141
backup_byok_identity=backup_byok_identity,
142142
backup_byok_key=backup_byok_key,
143143
performance_tier=performance_tier,
144-
create_cluster=create_cluster,
145144
password_auth=password_auth, microsoft_entra_auth=microsoft_entra_auth,
146-
admin_name=admin_name, admin_id=admin_id, admin_type=admin_type,)
145+
admin_name=admin_name, admin_id=admin_id, admin_type=admin_type, database_name=database_name)
147146

148147
cluster = None
149-
if create_cluster == 'ElasticCluster':
150-
cluster_size = cluster_size if cluster_size else 2
148+
if cluster_size is not None:
151149
cluster = postgresql_flexibleservers.models.Cluster(cluster_size=cluster_size, default_database_name=database_name if database_name else POSTGRES_DB_NAME)
152150

153151
server_result = firewall_id = None

src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/recordings/test_elastic_clusters_mgmt.yaml

Lines changed: 1087 additions & 368 deletions
Large diffs are not rendered by default.

src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_elastic_clusters.py

Lines changed: 67 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -31,62 +31,96 @@ def _test_elastic_clusters_mgmt(self, resource_group):
3131
location = self.postgres_location
3232
sku_name = 'Standard_D2ds_v4'
3333
tier = 'GeneralPurpose'
34-
cluster_name = self.create_random_name(SERVER_NAME_PREFIX, SERVER_NAME_MAX_LENGTH)
35-
cluster_size = 2
34+
non_cluster = self.create_random_name(SERVER_NAME_PREFIX, SERVER_NAME_MAX_LENGTH)
35+
cluster = self.create_random_name(SERVER_NAME_PREFIX, SERVER_NAME_MAX_LENGTH)
36+
cluster_restore = self.create_random_name(SERVER_NAME_PREFIX, SERVER_NAME_MAX_LENGTH)
37+
node_count = 2
38+
database = 'dbcluster'
39+
40+
# Try to create regular flexible server passing elastic cluster specific parameters to verify that they are not accepted for regular servers.
41+
self.cmd('postgres flexible-server create -g {} -n {} --sku-name {} \
42+
--version {} --database-name {}'
43+
.format(resource_group, cluster, sku_name, version, database),
44+
expect_failure=True)
45+
46+
# Create regular flexible server to verify that elastic cluster specific parameters are not accepted for update command as well.
47+
self.cmd('postgres flexible-server create -g {} -n {} --sku-name {} \
48+
--version {} --public-access Enabled'
49+
.format(resource_group, non_cluster, sku_name, version))
50+
51+
# Try to update regular flexible server with elastic cluster specific parameters to verify that they are not accepted for regular servers.
52+
self.cmd('postgres flexible-server update -g {} -n {} --node-count {}'
53+
.format(resource_group, non_cluster, node_count),
54+
expect_failure=True)
3655

3756
# Create elastic cluster
3857
self.cmd('postgres flexible-server create -g {} -n {} --sku-name {} \
39-
--version {} --cluster-option ElasticCluster --public-access Enabled'
40-
.format(resource_group, cluster_name, sku_name, version))
58+
--version {} --node-count {} --public-access Enabled'
59+
.format(resource_group, cluster, sku_name, version, node_count))
4160

42-
basic_info = self.cmd('postgres flexible-server show -g {} -n {}'.format(resource_group, cluster_name)).get_output_in_json()
43-
self.assertEqual(basic_info['name'], cluster_name)
44-
self.assertEqual(str(basic_info['location']).replace(' ', '').lower(), location)
45-
self.assertEqual(basic_info['resourceGroup'], resource_group)
46-
self.assertEqual(basic_info['sku']['name'], sku_name)
47-
self.assertEqual(basic_info['sku']['tier'], tier)
48-
self.assertEqual(basic_info['version'], version)
49-
self.assertEqual(basic_info['cluster']['clusterSize'], cluster_size)
61+
basic_info = self.cmd('postgres flexible-server show -g {} -n {}'.
62+
format(resource_group, cluster),
63+
checks=[
64+
JMESPathCheck('name', cluster),
65+
JMESPathCheck('resourceGroup', resource_group),
66+
JMESPathCheck('sku.name', sku_name),
67+
JMESPathCheck('sku.tier', tier),
68+
JMESPathCheck('version', version),
69+
JMESPathCheck('cluster.clusterSize', node_count)
70+
]).get_output_in_json()
71+
self.assertEqual(basic_info['location'].replace(' ', '').lower(), location)
5072

5173
# Test failures
5274
self.cmd('postgres flexible-server update -g {} -n {} --storage-auto-grow Enabled'
53-
.format(resource_group, cluster_name), expect_failure=True)
75+
.format(resource_group, cluster),
76+
expect_failure=True)
77+
5478
# Backend silently ignores if the cluster size is smaller than current size, and does not return error.
5579
# Also, the cluster size remains unchanged. Hence the check is added to verify that cluster size is not updated.
5680
# When control plane adds support for scaling down cluster size, this test should be updated accordingly.
5781
self.cmd('postgres flexible-server update -g {} -n {} --node-count {}'
58-
.format(resource_group, cluster_name, cluster_size - 1),
82+
.format(resource_group, cluster, node_count - 1),
5983
checks=[
60-
JMESPathCheck('cluster.clusterSize', cluster_size)])
84+
JMESPathCheck('cluster.clusterSize', node_count)])
85+
6186
# Same behavior with cluster size being set to 0, it doesn't return error, neither it changes the cluster size.
6287
self.cmd('postgres flexible-server update -g {} -n {} --node-count {}'
63-
.format(resource_group, cluster_name, 0),
88+
.format(resource_group, cluster, 0),
6489
checks=[
65-
JMESPathCheck('cluster.clusterSize', cluster_size)])
90+
JMESPathCheck('cluster.clusterSize', node_count)])
91+
6692
# If the cluster size is larger than current supported maximum (20), it will return error.
6793
self.cmd('postgres flexible-server update -g {} -n {} --node-count {}'
68-
.format(resource_group, cluster_name, 21), expect_failure=True)
94+
.format(resource_group, cluster, 21),
95+
expect_failure=True)
96+
6997
self.cmd('postgres flexible-server replica list -g {} -n {}'
70-
.format(resource_group, cluster_name), expect_failure=True)
98+
.format(resource_group, cluster),
99+
expect_failure=True)
100+
71101
self.cmd('postgres flexible-server db create -g {} -s {} -d dbclusterfail'
72-
.format(resource_group, cluster_name), expect_failure=True)
102+
.format(resource_group, cluster),
103+
expect_failure=True)
73104

74-
# Update cluster
75-
update_cluster_size = 4
76-
update_info = self.cmd('postgres flexible-server update -g {} -n {} --node-count {}'
77-
.format(resource_group, cluster_name, update_cluster_size)).get_output_in_json()
78-
self.assertEqual(update_info['cluster']['clusterSize'], update_cluster_size)
105+
# Grow cluster size and validate growth.
106+
update_node_count = 4
107+
self.cmd('postgres flexible-server update -g {} -n {} --node-count {}'
108+
.format(resource_group, cluster, update_node_count),
109+
checks=[
110+
JMESPathCheck('cluster.clusterSize', update_node_count)
111+
])
79112

80113
# Wait until snapshot is created
81114
os.environ.get(ENV_LIVE_TEST, False) and sleep(1800)
82115

83-
# Restore
84-
cluster_restore_name = self.create_random_name(SERVER_NAME_PREFIX, SERVER_NAME_MAX_LENGTH)
85-
restore_result = self.cmd('postgres flexible-server restore -g {} --name {} --source-server {}'
86-
.format(resource_group, cluster_restore_name, basic_info['id'])).get_output_in_json()
87-
self.assertEqual(restore_result['name'], cluster_restore_name)
88-
self.assertEqual(restore_result['cluster']['clusterSize'], update_cluster_size)
116+
# Restore cluster and validate the restored cluster has the same cluster size as source cluster
117+
self.cmd('postgres flexible-server restore -g {} --name {} --source-server {}'
118+
.format(resource_group, cluster_restore, basic_info['id']),
119+
checks=[
120+
JMESPathCheck('name', cluster_restore),
121+
JMESPathCheck('cluster.clusterSize', update_node_count)
122+
])
89123

90124
# Clean up
91-
self.cmd('postgres flexible-server delete -g {} -n {} --yes'.format(resource_group, cluster_name))
92-
self.cmd('postgres flexible-server delete -g {} -n {} --yes'.format(resource_group, cluster_restore_name))
125+
self.cmd('postgres flexible-server delete -g {} -n {} --yes'.format(resource_group, cluster))
126+
self.cmd('postgres flexible-server delete -g {} -n {} --yes'.format(resource_group, cluster_restore))

src/azure-cli/azure/cli/command_modules/postgresql/utils/validators.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ def retention_validator(ns):
9999

100100

101101
def db_renaming_cluster_validator(ns):
102-
if ns.database_name is not None and ns.create_cluster.lower() != 'elasticcluster':
102+
if ns.database_name is not None and ns.cluster_size is None:
103103
raise ArgumentUsageError('The --database-name argument can only be used '
104-
'when --cluster-option is set to "ElasticCluster".')
104+
'when --node-count is present, as it only applies to elastic clusters.')
105105

106106

107107
# Validates if a subnet id or name have been given by the user. If subnet id is given, vnet-name should not be provided.
@@ -150,7 +150,7 @@ def pg_arguments_validator(db_context, location, tier, sku_name, storage_gb, ser
150150
public_access=None, version=None, instance=None, geo_redundant_backup=None,
151151
byok_identity=None, byok_key=None, backup_byok_identity=None, backup_byok_key=None,
152152
auto_grow=None, performance_tier=None,
153-
storage_type=None, iops=None, throughput=None, create_cluster=None, cluster_size=None,
153+
storage_type=None, iops=None, throughput=None, cluster_size=None,
154154
password_auth=None, microsoft_entra_auth=None,
155155
admin_name=None, admin_id=None, admin_type=None):
156156
validate_server_name(db_context, server_name, 'Microsoft.DBforPostgreSQL/flexibleServers')
@@ -169,7 +169,7 @@ def pg_arguments_validator(db_context, location, tier, sku_name, storage_gb, ser
169169
sku_info = {k.lower(): v for k, v in sku_info.items()}
170170
single_az = list_location_capability_info['single_az']
171171
geo_backup_supported = list_location_capability_info['geo_backup_supported']
172-
_cluster_validator(create_cluster, cluster_size, auto_grow, version, instance)
172+
_cluster_validator(cluster_size, instance)
173173
_network_arg_validator(subnet, public_access)
174174
_pg_tier_validator(tier, sku_info) # need to be validated first
175175
if tier is None and instance is not None:
@@ -198,16 +198,8 @@ def pg_arguments_validator(db_context, location, tier, sku_name, storage_gb, ser
198198
admin_name, admin_id, admin_type, instance)
199199

200200

201-
def _cluster_validator(create_cluster, cluster_size, auto_grow, version, instance):
202-
if (create_cluster and create_cluster.lower() == 'elasticcluster') or \
203-
(instance and instance.cluster and instance.cluster.cluster_size > 0):
204-
if instance is None and version != '17':
205-
raise ValidationError('Elastic cluster is only supported for PostgreSQL version 17.')
206-
207-
if auto_grow and auto_grow.lower() != 'disabled':
208-
raise ValidationError('Storage auto-grow is not supported for elastic cluster.')
209-
210-
if cluster_size and instance and not instance.cluster:
201+
def _cluster_validator(cluster_size, instance):
202+
if cluster_size is not None and instance and not instance.cluster:
211203
raise ValidationError('Node count can only be specified for an elastic cluster.')
212204

213205

0 commit comments

Comments
 (0)