From 1c25ad2e5aa94826ca90eaa4b82a1474c885eead Mon Sep 17 00:00:00 2001 From: ShawnX Date: Wed, 2 Sep 2026 03:47:01 +0100 Subject: [PATCH 1/3] {MySQL} Update terminology for Memory Optimized tier and remove deprecated function --- .../cli/command_modules/mysql/_params.py | 2 +- .../azure/cli/command_modules/mysql/_util.py | 10 ----- .../cli/command_modules/mysql/_validators.py | 2 +- .../azure/cli/command_modules/mysql/custom.py | 11 +++--- .../mysql/tests/latest/test_mysql_custom.py | 38 +++++++++++++++++++ 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/mysql/_params.py b/src/azure-cli/azure/cli/command_modules/mysql/_params.py index a253fa274ca..2ae9efed8da 100644 --- a/src/azure-cli/azure/cli/command_modules/mysql/_params.py +++ b/src/azure-cli/azure/cli/command_modules/mysql/_params.py @@ -119,7 +119,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements, too-many- accelerated_logs_arg_type = CLIArgumentType( arg_type=get_enum_type(['Enabled', 'Disabled']), options_list=['--accelerated-logs'], - help='Enable or disable accelerated logs. Only support for Business Critical tier. Default value is Enabled.' + help='Enable or disable accelerated logs. Supported only for the Memory Optimized tier. Default value is Enabled.' ) faster_restore_arg_type = CLIArgumentType( diff --git a/src/azure-cli/azure/cli/command_modules/mysql/_util.py b/src/azure-cli/azure/cli/command_modules/mysql/_util.py index 7fe3f1ca8c5..89dd4d86396 100644 --- a/src/azure-cli/azure/cli/command_modules/mysql/_util.py +++ b/src/azure-cli/azure/cli/command_modules/mysql/_util.py @@ -477,16 +477,6 @@ def get_user_confirmation(message, yes=False): 'Unable to prompt for confirmation as no tty available. Use --yes.') -def replace_memory_optimized_tier(result): - result = _get_list_from_paged_response(result) - for capability in result: - for edition_idx, edition in enumerate(capability.supported_flexible_server_editions): - if edition.name == 'MemoryOptimized': - capability.supported_flexible_server_editions[edition_idx].name = 'BusinessCritical' - - return result - - def _is_resource_name(resource): if len(resource.split('/')) == 1: return True diff --git a/src/azure-cli/azure/cli/command_modules/mysql/_validators.py b/src/azure-cli/azure/cli/command_modules/mysql/_validators.py index 824abe205de..ca4c599aa55 100644 --- a/src/azure-cli/azure/cli/command_modules/mysql/_validators.py +++ b/src/azure-cli/azure/cli/command_modules/mysql/_validators.py @@ -214,7 +214,7 @@ def mysql_sku_name_validator(sku_name, sku_info, tier, instance): if sku_name not in skus: raise CLIError('Incorrect value for --sku-name. The SKU name does not match tier selection. ' 'Default value for --tier is Burstable. ' - 'For Business Critical and General Purpose you need to specify --tier value explicitly. ' + 'For Memory Optimized and General Purpose you need to specify --tier value explicitly. ' 'Allowed values for given tier: {}'.format(skus)) diff --git a/src/azure-cli/azure/cli/command_modules/mysql/custom.py b/src/azure-cli/azure/cli/command_modules/mysql/custom.py index 4b00fa295fd..5fa4136b998 100644 --- a/src/azure-cli/azure/cli/command_modules/mysql/custom.py +++ b/src/azure-cli/azure/cli/command_modules/mysql/custom.py @@ -26,7 +26,7 @@ cf_mysql_flexible_servers, cf_mysql_flexible_replica, cf_mysql_flexible_adadmin, cf_mysql_flexible_private_dns_zone_suffix_operations, cf_mysql_servers, \ cf_mysql_firewall_rules, get_mysql_flexible_management_client_by_sub from ._util import resolve_poller, generate_missing_parameters, get_mysql_list_skus_info, generate_password, parse_maintenance_window, \ - replace_memory_optimized_tier, build_identity_and_data_encryption, get_identity_and_data_encryption, get_tenant_id, run_subprocess, \ + _get_list_from_paged_response, build_identity_and_data_encryption, get_identity_and_data_encryption, get_tenant_id, run_subprocess, \ fill_action_template, get_git_root_dir, get_single_to_flex_sku_mapping, get_firewall_rules_from_paged_response, \ ImportFromStorageProgressHook, OperationProgressBar, GITHUB_ACTION_PATH from ._network import prepare_mysql_exist_private_dns_zone, prepare_mysql_exist_private_network, prepare_private_network, prepare_private_dns_zone, prepare_public_network @@ -360,7 +360,7 @@ def flexible_server_create(cmd, client, # Process parameters server_name = server_name.lower() - # MySQL chnged MemoryOptimized tier to BusinessCritical (only in client tool not in list-skus return) + # Accept BusinessCritical as a legacy alias; service capabilities use MemoryOptimized. if tier == 'BusinessCritical': tier = 'MemoryOptimized' mysql_arguments_validator(db_context, @@ -567,7 +567,7 @@ def flexible_server_import_create(cmd, client, # Process parameters server_name = server_name.lower() - # MySQL changed MemoryOptimized tier to BusinessCritical (only in client tool not in list-skus return) + # Accept BusinessCritical as a legacy alias; service capabilities use MemoryOptimized. if tier == 'BusinessCritical': tier = 'MemoryOptimized' mysql_arguments_validator(db_context, @@ -1016,7 +1016,7 @@ def flexible_server_update_custom_func(cmd, client, instance, sku_name=None, tie cf_availability_without_location=cf_mysql_check_resource_availability_without_location, logging_name='MySQL', command_group='mysql', server_client=client, location=instance.location) - # MySQL chnged MemoryOptimized tier to BusinessCritical (only in client tool not in list-skus return) + # Accept BusinessCritical as a legacy alias; service capabilities use MemoryOptimized. if tier == 'BusinessCritical': tier = 'MemoryOptimized' mysql_arguments_validator(db_context, @@ -1467,8 +1467,7 @@ def flexible_server_mysql_get(cmd, resource_group_name, server_name): def flexible_list_skus(cmd, client, location): - result = client.list(location) - result = replace_memory_optimized_tier(result) + result = _get_list_from_paged_response(client.list(location)) logger.warning('For prices please refer to https://aka.ms/mysql-pricing') return result diff --git a/src/azure-cli/azure/cli/command_modules/mysql/tests/latest/test_mysql_custom.py b/src/azure-cli/azure/cli/command_modules/mysql/tests/latest/test_mysql_custom.py index fee7b2f69c4..a8429179f55 100644 --- a/src/azure-cli/azure/cli/command_modules/mysql/tests/latest/test_mysql_custom.py +++ b/src/azure-cli/azure/cli/command_modules/mysql/tests/latest/test_mysql_custom.py @@ -34,6 +34,21 @@ def test_firewall_rule_create_uses_properties_payload(self): }, client.parameters.as_dict()) +class MysqlFlexibleServerListSkusCustomTest(unittest.TestCase): + + def test_list_skus_preserves_memory_optimized_tier(self): + capabilities = [_FakeCapability('MemoryOptimized')] + client = _FakeLocationCapabilitiesClient(capabilities) + + result = custom.flexible_list_skus(cmd=None, client=client, location='eastus') + + self.assertIs(capabilities, result) + self.assertEqual('eastus', client.location) + self.assertEqual( + 'MemoryOptimized', + result[0].supported_flexible_server_editions[0].name) + + class _FakeFirewallRulesClient: def begin_create_or_update(self, resource_group_name, server_name, firewall_rule_name, parameters): @@ -44,5 +59,28 @@ def begin_create_or_update(self, resource_group_name, server_name, firewall_rule return parameters +class _FakeCapability: + + def __init__(self, tier_name): + self.supported_flexible_server_editions = [_FakeEdition(tier_name)] + + +class _FakeEdition: + + def __init__(self, name): + self.name = name + + +class _FakeLocationCapabilitiesClient: + + def __init__(self, result): + self.result = result + self.location = None + + def list(self, location): + self.location = location + return self.result + + if __name__ == '__main__': unittest.main() From b4c7c9d9b80ae8986e65e8fa6b8fbd06a0901512 Mon Sep 17 00:00:00 2001 From: ShawnX Date: Wed, 2 Sep 2026 03:55:38 +0100 Subject: [PATCH 2/3] Update accelerated logs terminology and add unit tests for tier behavior --- .../azure/cli/command_modules/mysql/_params.py | 2 +- .../mysql/tests/latest/test_mysql_custom.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/mysql/_params.py b/src/azure-cli/azure/cli/command_modules/mysql/_params.py index 2ae9efed8da..1900ed1a28c 100644 --- a/src/azure-cli/azure/cli/command_modules/mysql/_params.py +++ b/src/azure-cli/azure/cli/command_modules/mysql/_params.py @@ -119,7 +119,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements, too-many- accelerated_logs_arg_type = CLIArgumentType( arg_type=get_enum_type(['Enabled', 'Disabled']), options_list=['--accelerated-logs'], - help='Enable or disable accelerated logs. Supported only for the Memory Optimized tier. Default value is Enabled.' + help='Enable or disable accelerated logs. Supported for General Purpose and Memory Optimized tiers.' ) faster_restore_arg_type = CLIArgumentType( diff --git a/src/azure-cli/azure/cli/command_modules/mysql/tests/latest/test_mysql_custom.py b/src/azure-cli/azure/cli/command_modules/mysql/tests/latest/test_mysql_custom.py index a8429179f55..b1cf4820b09 100644 --- a/src/azure-cli/azure/cli/command_modules/mysql/tests/latest/test_mysql_custom.py +++ b/src/azure-cli/azure/cli/command_modules/mysql/tests/latest/test_mysql_custom.py @@ -34,6 +34,23 @@ def test_firewall_rule_create_uses_properties_payload(self): }, client.parameters.as_dict()) +class MysqlAcceleratedLogsCustomTest(unittest.TestCase): + + def test_accelerated_logs_tier_behavior(self): + self.assertEqual( + 'Enabled', + custom._determine_acceleratedLogs('Enabled', 'GeneralPurpose')) + self.assertEqual( + 'Disabled', + custom._determine_acceleratedLogs(None, 'GeneralPurpose')) + self.assertEqual( + 'Enabled', + custom._determine_acceleratedLogs(None, 'MemoryOptimized')) + self.assertEqual( + 'Disabled', + custom._determine_acceleratedLogs('Enabled', 'Burstable')) + + class MysqlFlexibleServerListSkusCustomTest(unittest.TestCase): def test_list_skus_preserves_memory_optimized_tier(self): From 53aa825d36f1945f16a1e0a63e2dc01853744ba0 Mon Sep 17 00:00:00 2001 From: ShawnX Date: Wed, 2 Sep 2026 05:07:46 +0100 Subject: [PATCH 3/3] {MySQL} Normalize Memory Optimized tier terminology and update related tests to address copilot review comments --- .../cli/command_modules/mysql/_params.py | 6 +- .../azure/cli/command_modules/mysql/_util.py | 4 ++ .../azure/cli/command_modules/mysql/custom.py | 9 --- .../mysql/tests/latest/test_mysql_custom.py | 55 ++++++++++++++++++- 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/mysql/_params.py b/src/azure-cli/azure/cli/command_modules/mysql/_params.py index 1900ed1a28c..1346ee93374 100644 --- a/src/azure-cli/azure/cli/command_modules/mysql/_params.py +++ b/src/azure-cli/azure/cli/command_modules/mysql/_params.py @@ -13,7 +13,7 @@ from azure.cli.command_modules.mysql._validators import public_access_validator, maintenance_window_validator, ip_address_validator, \ firewall_rule_name_validator, validate_identity, validate_byok_identity, validate_identities, validate_action_name, validate_branch from azure.cli.core.local_context import LocalContextAttribute, LocalContextAction -from ._util import get_current_time +from ._util import get_current_time, normalize_mysql_tier from argcomplete.completers import FilesCompleter @@ -70,6 +70,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements, too-many- ) tier_arg_type = CLIArgumentType( + type=normalize_mysql_tier, options_list=['--tier'], help='Compute tier of the server. Accepted values: Burstable, GeneralPurpose, MemoryOptimized ' ) @@ -119,7 +120,8 @@ def load_arguments(self, _): # pylint: disable=too-many-statements, too-many- accelerated_logs_arg_type = CLIArgumentType( arg_type=get_enum_type(['Enabled', 'Disabled']), options_list=['--accelerated-logs'], - help='Enable or disable accelerated logs. Supported for General Purpose and Memory Optimized tiers.' + help='Enable or disable accelerated logs. Supported for General Purpose and Memory Optimized tiers. ' + 'For server creation, defaults to Enabled for Memory Optimized and Disabled for General Purpose.' ) faster_restore_arg_type = CLIArgumentType( diff --git a/src/azure-cli/azure/cli/command_modules/mysql/_util.py b/src/azure-cli/azure/cli/command_modules/mysql/_util.py index 89dd4d86396..dbe4ae30e66 100644 --- a/src/azure-cli/azure/cli/command_modules/mysql/_util.py +++ b/src/azure-cli/azure/cli/command_modules/mysql/_util.py @@ -224,6 +224,10 @@ def get_mysql_tiers(sku_info): return list(sku_info.keys()) +def normalize_mysql_tier(tier): + return 'MemoryOptimized' if tier == 'BusinessCritical' else tier + + def get_mysql_list_skus_info(cmd, location, server_name=None): list_skus_client = cf_mysql_flexible_location_capabilities(cmd.cli_ctx, '_') params = {'serverName': server_name} if server_name else None diff --git a/src/azure-cli/azure/cli/command_modules/mysql/custom.py b/src/azure-cli/azure/cli/command_modules/mysql/custom.py index 5fa4136b998..6425089aba2 100644 --- a/src/azure-cli/azure/cli/command_modules/mysql/custom.py +++ b/src/azure-cli/azure/cli/command_modules/mysql/custom.py @@ -360,9 +360,6 @@ def flexible_server_create(cmd, client, # Process parameters server_name = server_name.lower() - # Accept BusinessCritical as a legacy alias; service capabilities use MemoryOptimized. - if tier == 'BusinessCritical': - tier = 'MemoryOptimized' mysql_arguments_validator(db_context, server_name=server_name, location=location, @@ -567,9 +564,6 @@ def flexible_server_import_create(cmd, client, # Process parameters server_name = server_name.lower() - # Accept BusinessCritical as a legacy alias; service capabilities use MemoryOptimized. - if tier == 'BusinessCritical': - tier = 'MemoryOptimized' mysql_arguments_validator(db_context, data_source_type=data_source_type, mode=mode, @@ -1016,9 +1010,6 @@ def flexible_server_update_custom_func(cmd, client, instance, sku_name=None, tie cf_availability_without_location=cf_mysql_check_resource_availability_without_location, logging_name='MySQL', command_group='mysql', server_client=client, location=instance.location) - # Accept BusinessCritical as a legacy alias; service capabilities use MemoryOptimized. - if tier == 'BusinessCritical': - tier = 'MemoryOptimized' mysql_arguments_validator(db_context, location=location, tier=tier, diff --git a/src/azure-cli/azure/cli/command_modules/mysql/tests/latest/test_mysql_custom.py b/src/azure-cli/azure/cli/command_modules/mysql/tests/latest/test_mysql_custom.py index b1cf4820b09..26eeb07c81b 100644 --- a/src/azure-cli/azure/cli/command_modules/mysql/tests/latest/test_mysql_custom.py +++ b/src/azure-cli/azure/cli/command_modules/mysql/tests/latest/test_mysql_custom.py @@ -3,9 +3,11 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- import unittest -from unittest.mock import patch +from unittest.mock import MagicMock, patch from ... import custom +from ..._params import load_arguments +from ..._util import normalize_mysql_tier class MysqlFlexibleServerFirewallRuleCustomTest(unittest.TestCase): @@ -51,6 +53,39 @@ def test_accelerated_logs_tier_behavior(self): custom._determine_acceleratedLogs('Enabled', 'Burstable')) +class MysqlTierNormalizationTest(unittest.TestCase): + + def test_business_critical_is_normalized_as_legacy_alias(self): + self.assertEqual('MemoryOptimized', normalize_mysql_tier('BusinessCritical')) + self.assertEqual('MemoryOptimized', normalize_mysql_tier('MemoryOptimized')) + self.assertIsNone(normalize_mysql_tier(None)) + + def test_all_tier_arguments_use_legacy_alias_normalizer(self): + registrations = [] + loader = MagicMock() + loader.argument_context.side_effect = \ + lambda command_name: _FakeArgumentContext(command_name, registrations) + + load_arguments(loader, None) + + tier_arg_types = { + command_name: settings['arg_type'] + for command_name, argument_name, settings in registrations + if argument_name == 'tier' + } + self.assertEqual({ + 'mysql flexible-server create', + 'mysql flexible-server geo-restore', + 'mysql flexible-server import create', + 'mysql flexible-server replica create', + 'mysql flexible-server restore', + 'mysql flexible-server update' + }, set(tier_arg_types)) + for command_name, arg_type in tier_arg_types.items(): + with self.subTest(command_name=command_name): + self.assertIs(normalize_mysql_tier, arg_type.settings['type']) + + class MysqlFlexibleServerListSkusCustomTest(unittest.TestCase): def test_list_skus_preserves_memory_optimized_tier(self): @@ -99,5 +134,23 @@ def list(self, location): return self.result +class _FakeArgumentContext: + + def __init__(self, command_name, registrations): + self.command_name = command_name + self.registrations = registrations + + def __enter__(self): + return self + + def __exit__(self, *args): + return False + + def argument(self, argument_name, *args, **settings): + if args: + settings['arg_type'] = args[0] + self.registrations.append((self.command_name, argument_name, settings)) + + if __name__ == '__main__': unittest.main()