Skip to content

[PostgreSQL] az postgres flexible-server: Improve validation logic and style of error messages#33114

Open
nachoalonsoportillo wants to merge 7 commits intoAzure:devfrom
nachoalonsoportillo:review-style-of-error-messages
Open

[PostgreSQL] az postgres flexible-server: Improve validation logic and style of error messages#33114
nachoalonsoportillo wants to merge 7 commits intoAzure:devfrom
nachoalonsoportillo:review-style-of-error-messages

Conversation

@nachoalonsoportillo
Copy link
Copy Markdown
Member

@nachoalonsoportillo nachoalonsoportillo commented Apr 1, 2026

  • Updated comments in test files to improve clarity and consistency.
  • Enhanced error messages in validators for better user guidance and understanding.
  • Standardized phrasing and capitalization in error messages across various validators.
  • Improved validation logic to ensure clearer feedback for incorrect usage.

Related command
az postgres flexible-server

Description
Provided consistency to validations (now all are case-insensitive), and consistent style to error messages produced from validators/

Testing Guide
Ran all tests in live mode to get new recordings and make sure that they all pass.

History Notes

[PostgreSQL] az postgres flexible-server: Improve validation logic and style of error messages


This checklist is used to make sure that common guidelines for a pull request are followed.

- Updated comments in test files to improve clarity and consistency.
- Enhanced error messages in validators for better user guidance and understanding.
- Standardized phrasing and capitalization in error messages across various validators.
- Improved validation logic to ensure clearer feedback for incorrect usage.
Copilot AI review requested due to automatic review settings April 1, 2026 00:01
@azure-client-tools-bot-prd
Copy link
Copy Markdown

azure-client-tools-bot-prd bot commented Apr 1, 2026

❌AzureCLI-FullTest
️✔️acr
️✔️latest
️✔️3.12
️✔️3.13
️✔️acs
️✔️latest
️✔️3.12
️✔️3.13
️✔️advisor
️✔️latest
️✔️3.12
️✔️3.13
️✔️ams
️✔️latest
️✔️3.12
️✔️3.13
️✔️apim
️✔️latest
️✔️3.12
️✔️3.13
️✔️appconfig
️✔️latest
️✔️3.12
️✔️3.13
️✔️appservice
️✔️latest
️✔️3.12
️✔️3.13
️✔️aro
️✔️latest
️✔️3.12
️✔️3.13
️✔️backup
️✔️latest
️✔️3.12
️✔️3.13
️✔️batch
️✔️latest
️✔️3.12
️✔️3.13
️✔️batchai
️✔️latest
️✔️3.12
️✔️3.13
️✔️billing
️✔️latest
️✔️3.12
️✔️3.13
️✔️botservice
️✔️latest
️✔️3.12
️✔️3.13
️✔️cdn
️✔️latest
️✔️3.12
️✔️3.13
️✔️cloud
️✔️latest
️✔️3.12
️✔️3.13
️✔️cognitiveservices
️✔️latest
️✔️3.12
️✔️3.13
️✔️compute_recommender
️✔️latest
️✔️3.12
️✔️3.13
️✔️computefleet
️✔️latest
️✔️3.12
️✔️3.13
️✔️config
️✔️latest
️✔️3.12
️✔️3.13
️✔️configure
️✔️latest
️✔️3.12
️✔️3.13
️✔️consumption
️✔️latest
️✔️3.12
️✔️3.13
️✔️container
️✔️latest
️✔️3.12
️✔️3.13
️✔️containerapp
️✔️latest
️✔️3.12
️✔️3.13
️✔️core
️✔️latest
️✔️3.12
️✔️3.13
️✔️cosmosdb
️✔️latest
️✔️3.12
️✔️3.13
️✔️databoxedge
️✔️latest
️✔️3.12
️✔️3.13
️✔️dls
️✔️latest
️✔️3.12
️✔️3.13
️✔️dms
️✔️latest
️✔️3.12
️✔️3.13
️✔️eventgrid
️✔️latest
️✔️3.12
️✔️3.13
️✔️eventhubs
️✔️latest
️✔️3.12
️✔️3.13
️✔️feedback
️✔️latest
️✔️3.12
️✔️3.13
️✔️find
️✔️latest
️✔️3.12
️✔️3.13
️✔️hdinsight
️✔️latest
️✔️3.12
️✔️3.13
️✔️identity
️✔️latest
️✔️3.12
️✔️3.13
️✔️iot
️✔️latest
️✔️3.12
️✔️3.13
️✔️keyvault
️✔️latest
️✔️3.12
️✔️3.13
️✔️lab
️✔️latest
️✔️3.12
️✔️3.13
️✔️managedservices
️✔️latest
️✔️3.12
️✔️3.13
️✔️maps
️✔️latest
️✔️3.12
️✔️3.13
️✔️marketplaceordering
️✔️latest
️✔️3.12
️✔️3.13
️✔️monitor
️✔️latest
️✔️3.12
️✔️3.13
️✔️mysql
️✔️latest
️✔️3.12
️✔️3.13
️✔️netappfiles
️✔️latest
️✔️3.12
️✔️3.13
️✔️network
️✔️latest
️✔️3.12
️✔️3.13
️✔️policyinsights
️✔️latest
️✔️3.12
️✔️3.13
❌postgresql
❌latest
❌3.12
Type Test Case Error Message Line
Failed test_postgres_flexible_server_existing_private_dns_zone self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f12a264a120>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f12a603e960>
command = 'postgres flexible-server create -g clitest.rg000001 -n azuredbclitest-000003 -l canadacentral --private-dns-zone clit...s/clitest.rg000001/providers/Microsoft.Network/virtualNetworks/servergrouptestvnet/subnets/servergrouptestsubnet --yes'
expect_failure = False

    def in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
>           self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/azure-cli-testsdk/azure/cli/testsdk/base.py:303: 
                                        
env/lib/python3.12/site-packages/knack/cli.py:245: in invoke
    exit_code = self.exception_handler(ex)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/init.py:157: in exception_handler
    return handle_exception(ex)
           ^^^^^^^^^^^^^^^^^^^^
src/azure-cli-testsdk/azure/cli/testsdk/patches.py:33: in handle_main_exception
    raise ex
env/lib/python3.12/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:677: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:820: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:789: in run_job
    result = cmd_copy(params)
             ^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:335: in call
    return self.handler(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/command_operation.py:120: in handler
    return op(**command_args)
           ^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/postgresql/commands/custom_commands.py:155: in flexible_server_create
    network, start_ip, end_ip = flexible_server_provision_network_resource(cmd=cmd,
src/azure-cli/azure/cli/command_modules/postgresql/commands/network_commands.py:392: in flexible_server_provision_network_resource
    subnet_id = prepare_private_network(cmd,
src/azure-cli/azure/cli/command_modules/postgresql/commands/network_commands.py:86: in prepare_private_network
    subnet_result = process_private_network_with_id_input(cmd, subnet, nw_subscription, resource_client, server_name, location, delegation_service_name, vnet_address_pref, subnet_address_pref, yes)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/postgresql/commands/network_commands.py:119: in process_private_network_with_id_input
    return create_vnet_subnet_delegation(cmd, nw_subscription, resource_client, delegation_service_name, id_resource_group, id_vnet, id_subnet,
src/azure-cli/azure/cli/command_modules/postgresql/commands/network_commands.py:140: in create_vnet_subnet_delegation
    if not check_existence(resource_client, vnet_name, resource_group, 'Microsoft.Network', 'virtualNetworks'):
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/postgresql/utils/flexible_server_util.py:224: in check_existence
    resource = resource_client.resources.get(resource_group, provider_namespace, parent_path, resource_type, value, api_version)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/tracing/decorator.py:119: in wrapper_use_tracer
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/mgmt/resource/resources/v2024_11_01/operations/operations.py:5145: in get
    pipeline_response: PipelineResponse = self.client.pipeline.run(  # pylint: disable=protected-access
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:242: in run
    return first_node.send(pipeline_request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/mgmt/core/policies/base.py:95: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/policies/redirect.py:205: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/policies/retry.py:545: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/policies/authentication.py:194: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/base.py:130: in send
    self.sender.send(request.http_request, **request.context.options),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/azure/core/pipeline/transport/requests_basic.py:375: in send
    response = self.session.request(  # type: ignore
env/lib/python3.12/site-packages/requests/sessions.py:592: in request
    resp = self.send(prep, **send_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/requests/sessions.py:706: in send
    r = adapter.send(request, **kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.12/site-packages/requests/adapters.py:645: in send
    resp = conn.urlopen(
env/lib/python3.12/site-packages/urllib3/connectionpool.py:787: in urlopen
    response = self.make_request(
env/lib/python3.12/site-packages/urllib3/connectionpool.py:534: in make_request
    response = conn.getresponse()
               ^^^^^^^^^^^^^^^^^^
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
          

self = <VCRRequestsHTTPSConnection/mnt/vss/work/1/s/src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/recordings/test_postgres_flexible_server_existing_private_dns_zone.yaml(host='management.azure.com', port=443) at 0x7f12a23dda60>
 = False, kwargs = {}

    def getresponse(self, 
=False, **kwargs):
        """Retrieve the response"""
        # Check to see if the cassette has a response for this request. If so,
        # then return it
        if self.cassette.can_play_response_for(self.vcr_request):
            log.info(f"Playing response for {self.vcr_request} from cassette")
            response = self.cassette.play_response(self.vcr_request)
            return VCRHTTPResponse(response)
        else:
            if self.cassette.write_protected and self.cassette.filter_request(self.vcr_request):
>               raise CannotOverwriteExistingCassetteException(
                    cassette=self.cassette,
                    failed_request=self.vcr_request,
                )
E               vcr.errors.CannotOverwriteExistingCassetteException: Can't overwrite existing cassette ('/mnt/vss/work/1/s/src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/recordings/test_postgres_flexible_server_existing_private_dns_zone.yaml') in your current record mode ('once').
E               No match for the request (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.Network//virtualNetworks/servergrouptestvnet?api-version=2024-05-01>)&nbsp;was&nbsp;found.
E               Found 2 similar requests with 0 different matcher(s) :
E               
E               1 - (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.Network/virtualNetworks/servergrouptestvnet?api-version=2024-05-01>).
E               Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path', 'custom_request_query_matcher']
E               Matchers failed :
E               
E               2 - (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.Network/virtualNetworks/servergrouptestvnet?api-version=2024-05-01>).
E               Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path', 'custom_request_query_matcher']
E               Matchers failed :

env/lib/python3.12/site-packages/vcr/stubs/init.py:277: CannotOverwriteExistingCassetteException

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.postgresql.tests.latest.test_postgres_flexible_commands_private_dns_zone.PostgreSQLFlexibleServerPrivateDnsZoneScenarioTest testMethod=test_postgres_flexible_server_existing_private_dns_zone>
server_resource_group = 'clitest.rg000001'
vnet_resource_group = 'clitest.rg000002'

    @AllowLargeResponse()
    @ResourceGroupPreparer(location=postgres_location, parameter_name='server_resource_group')
    @ResourceGroupPreparer(location=postgres_location, parameter_name='vnet_resource_group')
    def test_postgres_flexible_server_existing_private_dns_zone(self, server_resource_group, vnet_resource_group):
>       self.test_flexible_server_existing_private_dns_zone(server_resource_group, vnet_resource_group)

src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_private_dns_zone.py:28: 
 
 
 
 
 
 
 
 
                                
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_private_dns_zone.py:80: in test_flexible_server_existing_private_dns_zone
    self.cmd('postgres flexible-server create -g {} -n {} -l {} --private-dns-zone {} --subnet {} --yes'.format(
src/azure-cli-testsdk/azure/cli/testsdk/base.py:177: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-testsdk/azure/cli/testsdk/base.py:252: in init
    self.in_process_execute(cli_ctx, command, expect_failure=expect_failure)
 
 
                                     _ 

self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f12a264a120>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f12a603e960>
command = 'postgres flexible-server create -g clitest.rg000001 -n azuredbclitest-000003 -l canadacentral --private-dns-zone clit...s/clitest.rg000001/providers/Microsoft.Network/virtualNetworks/servergrouptestvnet/subnets/servergrouptestsubnet --yes'
expect_failure = False

    def _in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
            self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0
            self.output = stdout_buf.getvalue()
            self.applog = logging_buf.getvalue()
    
        except CannotOverwriteExistingCassetteException as ex:
>           raise AssertionError(ex)
E           AssertionError: Can't overwrite existing cassette ('/mnt/vss/_work/1/s/src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/recordings/test_postgres_flexible_server_existing_private_dns_zone.yaml') in your current record mode ('once').
E           No match for the request (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.Network//virtualNetworks/servergrouptestvnet?api-version=2024-05-01>)&nbsp;was&nbsp;found.
E           Found 2 similar requests with 0 different matcher(s) :
E           
E           1 - (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.Network/virtualNetworks/servergrouptestvnet?api-version=2024-05-01>).
E           Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path', '_custom_request_query_matcher']
E           Matchers failed :
E           
E           2 - (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.Network/virtualNetworks/servergrouptestvnet?api-version=2024-05-01>).
E           Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path', '_custom_request_query_matcher']
E           Matchers failed :

src/azure-cli-testsdk/azure/cli/testsdk/base.py:308: AssertionError
azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_private_dns_zone.py:23
❌3.13
Type Test Case Error Message Line
Failed test_postgres_flexible_server_existing_private_dns_zone self = <azure.cli.testsdk.base.ExecutionResult object at 0x7fb30d59fb50>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7fb311d420d0>
command = 'postgres flexible-server create -g clitest.rg000001 -n azuredbclitest-000003 -l canadacentral --private-dns-zone clit...s/clitest.rg000001/providers/Microsoft.Network/virtualNetworks/servergrouptestvnet/subnets/servergrouptestsubnet --yes'
expect_failure = False

    def in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
>           self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

src/azure-cli-testsdk/azure/cli/testsdk/base.py:303: 
                                        
env/lib/python3.13/site-packages/knack/cli.py:245: in invoke
    exit_code = self.exception_handler(ex)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/init.py:157: in exception_handler
    return handle_exception(ex)
           ^^^^^^^^^^^^^^^^^^^^
src/azure-cli-testsdk/azure/cli/testsdk/patches.py:33: in handle_main_exception
    raise ex
env/lib/python3.13/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:677: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:820: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:789: in run_job
    result = cmd_copy(params)
             ^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/init.py:335: in call
    return self.handler(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-core/azure/cli/core/commands/command_operation.py:120: in handler
    return op(**command_args)
           ^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/postgresql/commands/custom_commands.py:155: in flexible_server_create
    network, start_ip, end_ip = flexible_server_provision_network_resource(cmd=cmd,
src/azure-cli/azure/cli/command_modules/postgresql/commands/network_commands.py:392: in flexible_server_provision_network_resource
    subnet_id = prepare_private_network(cmd,
src/azure-cli/azure/cli/command_modules/postgresql/commands/network_commands.py:86: in prepare_private_network
    subnet_result = process_private_network_with_id_input(cmd, subnet, nw_subscription, resource_client, server_name, location, delegation_service_name, vnet_address_pref, subnet_address_pref, yes)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/postgresql/commands/network_commands.py:119: in process_private_network_with_id_input
    return create_vnet_subnet_delegation(cmd, nw_subscription, resource_client, delegation_service_name, id_resource_group, id_vnet, id_subnet,
src/azure-cli/azure/cli/command_modules/postgresql/commands/network_commands.py:140: in create_vnet_subnet_delegation
    if not check_existence(resource_client, vnet_name, resource_group, 'Microsoft.Network', 'virtualNetworks'):
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli/azure/cli/command_modules/postgresql/utils/flexible_server_util.py:224: in check_existence
    resource = resource_client.resources.get(resource_group, provider_namespace, parent_path, resource_type, value, api_version)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/tracing/decorator.py:119: in wrapper_use_tracer
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/mgmt/resource/resources/v2024_11_01/operations/operations.py:5145: in get
    pipeline_response: PipelineResponse = self.client.pipeline.run(  # pylint: disable=protected-access
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:242: in run
    return first_node.send(pipeline_request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/mgmt/core/policies/base.py:95: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/policies/redirect.py:205: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/policies/retry.py:545: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/policies/authentication.py:194: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:98: in send
    response = self.next.send(request)
               ^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/base.py:130: in send
    self.sender.send(request.http_request, **request.context.options),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/azure/core/pipeline/transport/requests_basic.py:375: in send
    response = self.session.request(  # type: ignore
env/lib/python3.13/site-packages/requests/sessions.py:592: in request
    resp = self.send(prep, **send_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/requests/sessions.py:706: in send
    r = adapter.send(request, **kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
env/lib/python3.13/site-packages/requests/adapters.py:645: in send
    resp = conn.urlopen(
env/lib/python3.13/site-packages/urllib3/connectionpool.py:787: in urlopen
    response = self.make_request(
env/lib/python3.13/site-packages/urllib3/connectionpool.py:534: in make_request
    response = conn.getresponse()
               ^^^^^^^^^^^^^^^^^^
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
          

self = <VCRRequestsHTTPSConnection/mnt/vss/work/1/s/src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/recordings/test_postgres_flexible_server_existing_private_dns_zone.yaml(host='management.azure.com', port=443) at 0x7fb30d66a5f0>
 = False, kwargs = {}

    def getresponse(self, 
=False, **kwargs):
        """Retrieve the response"""
        # Check to see if the cassette has a response for this request. If so,
        # then return it
        if self.cassette.can_play_response_for(self.vcr_request):
            log.info(f"Playing response for {self.vcr_request} from cassette")
            response = self.cassette.play_response(self.vcr_request)
            return VCRHTTPResponse(response)
        else:
            if self.cassette.write_protected and self.cassette.filter_request(self.vcr_request):
>               raise CannotOverwriteExistingCassetteException(
                    cassette=self.cassette,
                    failed_request=self.vcr_request,
                )
E               vcr.errors.CannotOverwriteExistingCassetteException: Can't overwrite existing cassette ('/mnt/vss/work/1/s/src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/recordings/test_postgres_flexible_server_existing_private_dns_zone.yaml') in your current record mode ('once').
E               No match for the request (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.Network//virtualNetworks/servergrouptestvnet?api-version=2024-05-01>)&nbsp;was&nbsp;found.
E               Found 2 similar requests with 0 different matcher(s) :
E               
E               1 - (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.Network/virtualNetworks/servergrouptestvnet?api-version=2024-05-01>).
E               Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path', 'custom_request_query_matcher']
E               Matchers failed :
E               
E               2 - (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.Network/virtualNetworks/servergrouptestvnet?api-version=2024-05-01>).
E               Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path', 'custom_request_query_matcher']
E               Matchers failed :

env/lib/python3.13/site-packages/vcr/stubs/init.py:277: CannotOverwriteExistingCassetteException

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.postgresql.tests.latest.test_postgres_flexible_commands_private_dns_zone.PostgreSQLFlexibleServerPrivateDnsZoneScenarioTest testMethod=test_postgres_flexible_server_existing_private_dns_zone>
server_resource_group = 'clitest.rg000001'
vnet_resource_group = 'clitest.rg000002'

    @AllowLargeResponse()
    @ResourceGroupPreparer(location=postgres_location, parameter_name='server_resource_group')
    @ResourceGroupPreparer(location=postgres_location, parameter_name='vnet_resource_group')
    def test_postgres_flexible_server_existing_private_dns_zone(self, server_resource_group, vnet_resource_group):
>       self.test_flexible_server_existing_private_dns_zone(server_resource_group, vnet_resource_group)

src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_private_dns_zone.py:28: 
 
 
 
 
 
 
 
 
                                
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_private_dns_zone.py:80: in test_flexible_server_existing_private_dns_zone
    self.cmd('postgres flexible-server create -g {} -n {} -l {} --private-dns-zone {} --subnet {} --yes'.format(
src/azure-cli-testsdk/azure/cli/testsdk/base.py:177: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/azure-cli-testsdk/azure/cli/testsdk/base.py:252: in init
    self.in_process_execute(cli_ctx, command, expect_failure=expect_failure)
 
 
                                     _ 

self = <azure.cli.testsdk.base.ExecutionResult object at 0x7fb30d59fb50>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7fb311d420d0>
command = 'postgres flexible-server create -g clitest.rg000001 -n azuredbclitest-000003 -l canadacentral --private-dns-zone clit...s/clitest.rg000001/providers/Microsoft.Network/virtualNetworks/servergrouptestvnet/subnets/servergrouptestsubnet --yes'
expect_failure = False

    def _in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
            self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0
            self.output = stdout_buf.getvalue()
            self.applog = logging_buf.getvalue()
    
        except CannotOverwriteExistingCassetteException as ex:
>           raise AssertionError(ex)
E           AssertionError: Can't overwrite existing cassette ('/mnt/vss/_work/1/s/src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/recordings/test_postgres_flexible_server_existing_private_dns_zone.yaml') in your current record mode ('once').
E           No match for the request (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.Network//virtualNetworks/servergrouptestvnet?api-version=2024-05-01>)&nbsp;was&nbsp;found.
E           Found 2 similar requests with 0 different matcher(s) :
E           
E           1 - (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.Network/virtualNetworks/servergrouptestvnet?api-version=2024-05-01>).
E           Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path', '_custom_request_query_matcher']
E           Matchers failed :
E           
E           2 - (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001/providers/Microsoft.Network/virtualNetworks/servergrouptestvnet?api-version=2024-05-01>).
E           Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path', '_custom_request_query_matcher']
E           Matchers failed :

src/azure-cli-testsdk/azure/cli/testsdk/base.py:308: AssertionError
azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_private_dns_zone.py:23
️✔️privatedns
️✔️latest
️✔️3.12
️✔️3.13
️✔️profile
️✔️latest
️✔️3.12
️✔️3.13
️✔️rdbms
️✔️latest
️✔️3.12
️✔️3.13
️✔️redis
️✔️latest
️✔️3.12
️✔️3.13
️✔️relay
️✔️latest
️✔️3.12
️✔️3.13
️✔️resource
️✔️latest
️✔️3.12
️✔️3.13
️✔️role
️✔️latest
️✔️3.12
️✔️3.13
️✔️search
️✔️latest
️✔️3.12
️✔️3.13
️✔️security
️✔️latest
️✔️3.12
️✔️3.13
️✔️servicebus
️✔️latest
️✔️3.12
️✔️3.13
️✔️serviceconnector
️✔️latest
️✔️3.12
️✔️3.13
️✔️servicefabric
️✔️latest
️✔️3.12
️✔️3.13
️✔️signalr
️✔️latest
️✔️3.12
️✔️3.13
️✔️sql
️✔️latest
️✔️3.12
️✔️3.13
️✔️sqlvm
️✔️latest
️✔️3.12
️✔️3.13
️✔️storage
️✔️latest
️✔️3.12
️✔️3.13
️✔️synapse
️✔️latest
️✔️3.12
️✔️3.13
️✔️telemetry
️✔️latest
️✔️3.12
️✔️3.13
️✔️util
️✔️latest
️✔️3.12
️✔️3.13
️✔️vm
️✔️latest
️✔️3.12
️✔️3.13

@azure-client-tools-bot-prd
Copy link
Copy Markdown

azure-client-tools-bot-prd bot commented Apr 1, 2026

️✔️AzureCLI-BreakingChangeTest
️✔️Non Breaking Changes

@yonzhan
Copy link
Copy Markdown
Collaborator

yonzhan commented Apr 1, 2026

Thank you for your contribution! We will review the pull request and get back to you soon.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

The git hooks are available for azure-cli and azure-cli-extensions repos. They could help you run required checks before creating the PR.

Please sync the latest code with latest dev branch (for azure-cli) or main branch (for azure-cli-extensions).
After that please run the following commands to enable git hooks:

pip install azdev --upgrade
azdev setup -c <your azure-cli repo path> -r <your azure-cli-extensions repo path>

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the az postgres flexible-server user experience by standardizing validator behavior (case-insensitive comparisons) and making validator error messages clearer and more consistent, along with updating test comments for clarity.

Changes:

  • Standardize/clarify many validator error messages and make several validations case-insensitive.
  • Refine validation logic around elastic clusters, SSDv2 storage, HA/zonal resiliency, maintenance window, public access, etc.
  • Update PostgreSQL flexible-server scenario tests with clearer step comments and additional negative-test scenarios.

Reviewed changes

Copilot reviewed 19 out of 48 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/azure-cli/azure/cli/command_modules/postgresql/utils/validators.py Updates validator logic and standardizes error message wording/capitalization.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands.py Improves scenario test comments and expands validator negative-test coverage.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_vnet.py Comment-only clarity improvements for vnet scenarios.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_upgrade.py Comment-only clarity improvements for upgrade scenario.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_ssdv2.py Comment-only clarity improvements for SSDv2 scenarios.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_server_logs.py Comment-only clarity improvements for server logs scenarios.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_restore.py Comment-only clarity improvements for restore scenarios.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_replica.py Comment-only clarity improvements for replica/virtual endpoint scenarios.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_private_dns_zone.py Comment updates and scenarios around private DNS zone validation/linking.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_migration.py Comment-only clarity improvements for migration scenarios.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_ltr.py Comment-only clarity improvements for long-term retention scenarios.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_identity_microsoft_entra_admin.py Comment-only clarity improvements for identity/Entra admin scenarios.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_identity_cmk.py Comment-only clarity improvements for CMK scenarios.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_geo_restore.py Comment-only clarity improvements for geo-restore scenario.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_firewall_rule.py Comment-only clarity improvements for firewall/public access scenarios.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_fabric_mirroring.py Comment-only clarity improvements for fabric mirroring scenario.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_elastic_clusters.py Comment-only clarity improvements for elastic cluster scenario.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_backup.py Comment-only clarity improvements for backup scenarios.
src/azure-cli/azure/cli/command_modules/postgresql/tests/latest/test_postgres_flexible_commands_advanced_threat_protection.py Comment-only clarity improvements for ATP setting scenario.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 48 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 48 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 48 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 48 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (6)

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

  • ns.create_cluster.lower() will raise an AttributeError if ns.create_cluster is None (previous logic was != 'ElasticCluster' which was None-safe). Guard ns.create_cluster before calling .lower() (e.g., include a truthy check) to preserve previous behavior while keeping case-insensitivity.
    src/azure-cli/azure/cli/command_modules/postgresql/utils/validators.py:1
  • tier.lower() can raise an AttributeError when tier is None (e.g., in create flows where instance is None and tier was not provided). This regression comes from switching from tier == 'Burstable' to tier.lower() == 'burstable' without a guard. Fix by checking tier is set before calling .lower(), or by normalizing tier earlier (e.g., defaulting / deriving it before these checks).
    src/azure-cli/azure/cli/command_modules/postgresql/utils/validators.py:1
  • tier.lower() can raise an AttributeError when tier is None (e.g., in create flows where instance is None and tier was not provided). This regression comes from switching from tier == 'Burstable' to tier.lower() == 'burstable' without a guard. Fix by checking tier is set before calling .lower(), or by normalizing tier earlier (e.g., defaulting / deriving it before these checks).
    src/azure-cli/azure/cli/command_modules/postgresql/utils/validators.py:1
  • PR description states validations are now case-insensitive, but this tier check remains case-sensitive (tier == 'Burstable'). To align behavior, update the condition to a case-insensitive check (and keep it None-safe) so inputs like burstable behave consistently with the rest of the validators changed in this PR.
    src/azure-cli/azure/cli/command_modules/postgresql/utils/validators.py:1
  • This warning hard-codes a future date ("August 1, 2026"), which will become stale and potentially misleading over time. Consider removing the specific date (or referencing documentation/a config-driven policy) so the message remains accurate without requiring future code updates.
    src/azure-cli/azure/cli/command_modules/postgresql/utils/validators.py:1
  • This calls args.get('storage_type') twice and splits a boolean expression across lines in a way that’s harder to read. Assign storage_type = args.get('storage_type') once and base the check on that variable to improve readability and reduce duplication.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@calvinhzy
Copy link
Copy Markdown
Member

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@nachoalonsoportillo nachoalonsoportillo changed the title [PostgreSQL] az postgres flexible-server: Improved validation logic and style of error messages [PostgreSQL] az postgres flexible-server: Improve validation logic and style of error messages Apr 7, 2026
@calvinhzy
Copy link
Copy Markdown
Member

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants