Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
# --------------------------------------------------------------------------------------------

from azure.cli.core.breaking_change import (
NextBreakingChangeWindow,
register_argument_deprecate,
register_command_group_deprecate,
register_other_breaking_change
Expand Down Expand Up @@ -111,12 +110,3 @@ def _register_network_resource_breaking_change(command_name):

# Replica command argument changes
register_argument_deprecate('postgres flexible-server replica create', '--replica-name', redirect='--name')

# Elastic cluster command argument deprecated and will be removed in the future. Today,
# users must specify both --cluster-option ElasticCluster and --node-count to create an
# elastic cluster. In the future, providing --node-count alone will imply an elastic cluster.
register_argument_deprecate(command='postgres flexible-server create', argument='--cluster-option',
message='Currently, to create an elastic cluster you must specify '
'--cluster-option ElasticCluster together with --node-count. In the '
'future, providing --node-count alone will imply an elastic cluster.',
target_version=NextBreakingChangeWindow())
6 changes: 3 additions & 3 deletions src/azure-cli/azure/cli/command_modules/postgresql/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,9 @@
az postgres flexible-server create -g testGroup -n testServer --location testLocation --storage-auto-grow Enabled

- name: >
Create elastic cluster with node count of 5. Default node count is 2 when --cluster-option is "ElasticCluster".
Create elastic cluster with node count of 5.
text: >
az postgres flexible-server create -g testGroup -n testCluster --location testLocation --cluster-option ElasticCluster --node-count 5
az postgres flexible-server create -g testGroup -n testCluster --location testLocation --node-count 5
"""

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

Expand Down
12 changes: 2 additions & 10 deletions src/azure-cli/azure/cli/command_modules/postgresql/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def _flexible_server_params(command_group):
database_name_arg_type_cluster = CLIArgumentType(
metavar='NAME',
options_list=['--database-name', '-d'],
help='The default database name for an elastic cluster. Only applicable when --cluster-option is set to ElasticCluster.',
help='The default database name for an elastic cluster. Only applicable when --node-count is present.',
local_context_attribute=LocalContextAttribute(
name='database_name',
actions=[LocalContextAction.GET, LocalContextAction.SET],
Expand Down Expand Up @@ -146,17 +146,10 @@ def _flexible_server_params(command_group):
'This value can only be updated if flexible server is using Premium SSD v2 Disks.'
)

cluster_option_arg_type = CLIArgumentType(
arg_type=get_enum_type(['Server', 'ElasticCluster']),
options_list=['--cluster-option'],
help='Cluster option for the server. Servers are for workloads that can fit on one node. '
'Elastic clusters provides schema- and row-based sharding on a database. Default value is Server.'
)

create_node_count_arg_type = CLIArgumentType(
type=int,
options_list=['--node-count'],
help='The number of nodes for elastic cluster. Default is 2 nodes.'
help='The number of nodes for elastic cluster.'
)

update_node_count_arg_type = CLIArgumentType(
Expand Down Expand Up @@ -408,7 +401,6 @@ def _flexible_server_params(command_group):
c.argument('iops', default=None, arg_type=iops_v2_arg_type)
c.argument('throughput', default=None, arg_type=throughput_arg_type)
c.argument('performance_tier', default=None, arg_type=performance_tier_arg_type)
c.argument('create_cluster', default='Server', arg_type=cluster_option_arg_type)
c.argument('cluster_size', default=None, arg_type=create_node_count_arg_type)
c.argument('zonal_resiliency', arg_type=zonal_resiliency_arg_type, default="Disabled")
c.argument('allow_same_zone', arg_type=allow_same_zone_arg_type, default=False)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def flexible_server_create(cmd, client,
zone=None, standby_availability_zone=None,
geo_redundant_backup=None, byok_identity=None, byok_key=None, backup_byok_identity=None, backup_byok_key=None,
auto_grow=None, performance_tier=None,
storage_type=None, iops=None, throughput=None, create_cluster=None, cluster_size=None, database_name=None, yes=False):
storage_type=None, iops=None, throughput=None, cluster_size=None, database_name=None, yes=False):

if not check_resource_group(resource_group_name):
resource_group_name = None
Expand Down Expand Up @@ -141,13 +141,11 @@ def flexible_server_create(cmd, client,
backup_byok_identity=backup_byok_identity,
backup_byok_key=backup_byok_key,
performance_tier=performance_tier,
create_cluster=create_cluster,
password_auth=password_auth, microsoft_entra_auth=microsoft_entra_auth,
admin_name=admin_name, admin_id=admin_id, admin_type=admin_type,)
admin_name=admin_name, admin_id=admin_id, admin_type=admin_type, database_name=database_name)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is passing database_name related to removing the deprecated cluster option? Should this be a separate PR and is it fixing an existing bug/exposing new functionality?


cluster = None
if create_cluster == 'ElasticCluster':
cluster_size = cluster_size if cluster_size else 2
if cluster_size is not None:
cluster = postgresql_flexibleservers.models.Cluster(cluster_size=cluster_size, default_database_name=database_name if database_name else POSTGRES_DB_NAME)

server_result = firewall_id = None
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -31,62 +31,96 @@ def _test_elastic_clusters_mgmt(self, resource_group):
location = self.postgres_location
sku_name = 'Standard_D2ds_v4'
tier = 'GeneralPurpose'
cluster_name = self.create_random_name(SERVER_NAME_PREFIX, SERVER_NAME_MAX_LENGTH)
cluster_size = 2
non_cluster = self.create_random_name(SERVER_NAME_PREFIX, SERVER_NAME_MAX_LENGTH)
cluster = self.create_random_name(SERVER_NAME_PREFIX, SERVER_NAME_MAX_LENGTH)
cluster_restore = self.create_random_name(SERVER_NAME_PREFIX, SERVER_NAME_MAX_LENGTH)
node_count = 2
database = 'dbcluster'

# Try to create regular flexible server passing elastic cluster specific parameters to verify that they are not accepted for regular servers.
self.cmd('postgres flexible-server create -g {} -n {} --sku-name {} \
--version {} --database-name {}'
.format(resource_group, cluster, sku_name, version, database),
expect_failure=True)

# Create regular flexible server to verify that elastic cluster specific parameters are not accepted for update command as well.
self.cmd('postgres flexible-server create -g {} -n {} --sku-name {} \
--version {} --public-access Enabled'
.format(resource_group, non_cluster, sku_name, version))

# Try to update regular flexible server with elastic cluster specific parameters to verify that they are not accepted for regular servers.
self.cmd('postgres flexible-server update -g {} -n {} --node-count {}'
.format(resource_group, non_cluster, node_count),
expect_failure=True)

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

basic_info = self.cmd('postgres flexible-server show -g {} -n {}'.format(resource_group, cluster_name)).get_output_in_json()
self.assertEqual(basic_info['name'], cluster_name)
self.assertEqual(str(basic_info['location']).replace(' ', '').lower(), location)
self.assertEqual(basic_info['resourceGroup'], resource_group)
self.assertEqual(basic_info['sku']['name'], sku_name)
self.assertEqual(basic_info['sku']['tier'], tier)
self.assertEqual(basic_info['version'], version)
self.assertEqual(basic_info['cluster']['clusterSize'], cluster_size)
basic_info = self.cmd('postgres flexible-server show -g {} -n {}'.
format(resource_group, cluster),
checks=[
JMESPathCheck('name', cluster),
JMESPathCheck('resourceGroup', resource_group),
Comment thread
nachoalonsoportillo marked this conversation as resolved.
JMESPathCheck('sku.name', sku_name),
JMESPathCheck('sku.tier', tier),
JMESPathCheck('version', version),
JMESPathCheck('cluster.clusterSize', node_count)
]).get_output_in_json()
self.assertEqual(basic_info['location'].replace(' ', '').lower(), location)

# Test failures
self.cmd('postgres flexible-server update -g {} -n {} --storage-auto-grow Enabled'
.format(resource_group, cluster_name), expect_failure=True)
.format(resource_group, cluster),
expect_failure=True)

# Backend silently ignores if the cluster size is smaller than current size, and does not return error.
# Also, the cluster size remains unchanged. Hence the check is added to verify that cluster size is not updated.
# When control plane adds support for scaling down cluster size, this test should be updated accordingly.
self.cmd('postgres flexible-server update -g {} -n {} --node-count {}'
.format(resource_group, cluster_name, cluster_size - 1),
.format(resource_group, cluster, node_count - 1),
checks=[
JMESPathCheck('cluster.clusterSize', cluster_size)])
JMESPathCheck('cluster.clusterSize', node_count)])

# Same behavior with cluster size being set to 0, it doesn't return error, neither it changes the cluster size.
self.cmd('postgres flexible-server update -g {} -n {} --node-count {}'
.format(resource_group, cluster_name, 0),
.format(resource_group, cluster, 0),
checks=[
JMESPathCheck('cluster.clusterSize', cluster_size)])
JMESPathCheck('cluster.clusterSize', node_count)])

# If the cluster size is larger than current supported maximum (20), it will return error.
self.cmd('postgres flexible-server update -g {} -n {} --node-count {}'
.format(resource_group, cluster_name, 21), expect_failure=True)
.format(resource_group, cluster, 21),
expect_failure=True)

self.cmd('postgres flexible-server replica list -g {} -n {}'
.format(resource_group, cluster_name), expect_failure=True)
.format(resource_group, cluster),
expect_failure=True)

self.cmd('postgres flexible-server db create -g {} -s {} -d dbclusterfail'
.format(resource_group, cluster_name), expect_failure=True)
.format(resource_group, cluster),
expect_failure=True)

# Update cluster
update_cluster_size = 4
update_info = self.cmd('postgres flexible-server update -g {} -n {} --node-count {}'
.format(resource_group, cluster_name, update_cluster_size)).get_output_in_json()
self.assertEqual(update_info['cluster']['clusterSize'], update_cluster_size)
# Grow cluster size and validate growth.
update_node_count = 4
self.cmd('postgres flexible-server update -g {} -n {} --node-count {}'
.format(resource_group, cluster, update_node_count),
checks=[
JMESPathCheck('cluster.clusterSize', update_node_count)
])

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

# Restore
cluster_restore_name = self.create_random_name(SERVER_NAME_PREFIX, SERVER_NAME_MAX_LENGTH)
restore_result = self.cmd('postgres flexible-server restore -g {} --name {} --source-server {}'
.format(resource_group, cluster_restore_name, basic_info['id'])).get_output_in_json()
self.assertEqual(restore_result['name'], cluster_restore_name)
self.assertEqual(restore_result['cluster']['clusterSize'], update_cluster_size)
# Restore cluster and validate the restored cluster has the same cluster size as source cluster
self.cmd('postgres flexible-server restore -g {} --name {} --source-server {}'
.format(resource_group, cluster_restore, basic_info['id']),
checks=[
JMESPathCheck('name', cluster_restore),
JMESPathCheck('cluster.clusterSize', update_node_count)
])

# Clean up
self.cmd('postgres flexible-server delete -g {} -n {} --yes'.format(resource_group, cluster_name))
self.cmd('postgres flexible-server delete -g {} -n {} --yes'.format(resource_group, cluster_restore_name))
self.cmd('postgres flexible-server delete -g {} -n {} --yes'.format(resource_group, cluster))
self.cmd('postgres flexible-server delete -g {} -n {} --yes'.format(resource_group, cluster_restore))
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ def retention_validator(ns):


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


# Validates if a subnet id or name have been given by the user. If subnet id is given, vnet-name should not be provided.
Expand Down Expand Up @@ -150,7 +150,7 @@ def pg_arguments_validator(db_context, location, tier, sku_name, storage_gb, ser
public_access=None, version=None, instance=None, geo_redundant_backup=None,
byok_identity=None, byok_key=None, backup_byok_identity=None, backup_byok_key=None,
auto_grow=None, performance_tier=None,
storage_type=None, iops=None, throughput=None, create_cluster=None, cluster_size=None,
storage_type=None, iops=None, throughput=None, cluster_size=None,
password_auth=None, microsoft_entra_auth=None,
admin_name=None, admin_id=None, admin_type=None):
validate_server_name(db_context, server_name, 'Microsoft.DBforPostgreSQL/flexibleServers')
Expand All @@ -169,7 +169,7 @@ def pg_arguments_validator(db_context, location, tier, sku_name, storage_gb, ser
sku_info = {k.lower(): v for k, v in sku_info.items()}
single_az = list_location_capability_info['single_az']
geo_backup_supported = list_location_capability_info['geo_backup_supported']
_cluster_validator(create_cluster, cluster_size, auto_grow, version, instance)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is auto_grow and version removed from the validation?

_cluster_validator(cluster_size, instance)
_network_arg_validator(subnet, public_access)
_pg_tier_validator(tier, sku_info) # need to be validated first
if tier is None and instance is not None:
Expand Down Expand Up @@ -198,16 +198,8 @@ def pg_arguments_validator(db_context, location, tier, sku_name, storage_gb, ser
admin_name, admin_id, admin_type, instance)


def _cluster_validator(create_cluster, cluster_size, auto_grow, version, instance):
if (create_cluster and create_cluster.lower() == 'elasticcluster') or \
(instance and instance.cluster and instance.cluster.cluster_size > 0):
if instance is None and version != '17':
raise ValidationError('Elastic cluster is only supported for PostgreSQL version 17.')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is supported for version 17 and up. If we get sensible messages from the control plane then we can indeed drop CLI validation.


if auto_grow and auto_grow.lower() != 'disabled':
raise ValidationError('Storage auto-grow is not supported for elastic cluster.')

if cluster_size and instance and not instance.cluster:
def _cluster_validator(cluster_size, instance):
if cluster_size is not None and instance and not instance.cluster:
raise ValidationError('Node count can only be specified for an elastic cluster.')


Expand Down
Loading