From 66f9885569946e1be032045eea30e44cc31bb336 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 31 Jul 2026 23:59:43 +0000 Subject: [PATCH 1/3] Initial plan From fae402a1a4ecd8efdb1d4d712133b9a740618e08 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 1 Aug 2026 00:12:08 +0000 Subject: [PATCH 2/3] fix: webapp config set generic-configurations now correctly handles camelCase properties like webJobsEnabled --- .../cli/command_modules/appservice/custom.py | 16 ++++++-- .../latest/test_webapp_commands_thru_mock.py | 38 +++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/appservice/custom.py b/src/azure-cli/azure/cli/command_modules/appservice/custom.py index 0f247b322e2..3d20c62c747 100644 --- a/src/azure-cli/azure/cli/command_modules/appservice/custom.py +++ b/src/azure-cli/azure/cli/command_modules/appservice/custom.py @@ -3975,9 +3975,9 @@ def update_site_configs(cmd, resource_group_name, name, slot=None, number_of_wor result = {} for s in generic_configurations: try: - json_object = get_json_object(s) + json_object = shell_safe_json_parse(s) for config_name in json_object: - if config_name.lower() == 'ip_security_restrictions': + if config_name.lower() in ('ip_security_restrictions', 'ipsecurityrestrictions'): updating_ip_security_restrictions = True result.update(json_object) except CLIError: @@ -3985,9 +3985,17 @@ def update_site_configs(cmd, resource_group_name, name, slot=None, number_of_wor result[config_name] = value for config_name, value in result.items(): - if config_name.lower() == 'ip_security_restrictions': + if config_name.lower() in ('ip_security_restrictions', 'ipsecurityrestrictions'): updating_ip_security_restrictions = True - setattr(configs, config_name, value) + # In azure-mgmt-web 11.0.0+, SiteConfig is a MutableMapping with camelCase REST API keys. + # setattr works for known snake_case SDK property aliases (e.g., 'request_tracing_enabled'), + # but silently creates a Python attribute (not a dict entry) for unknown properties. + # Use dict-style assignment for camelCase property names so they are always included + # in the API request body (e.g., 'webJobsEnabled' which is not in the SDK model). + if any(c.isupper() for c in config_name): + configs[config_name] = value + else: + setattr(configs, config_name, value) if not updating_ip_security_restrictions: setattr(configs, 'ip_security_restrictions', None) diff --git a/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_webapp_commands_thru_mock.py b/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_webapp_commands_thru_mock.py index 697496f307c..66bd616b3e5 100644 --- a/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_webapp_commands_thru_mock.py +++ b/src/azure-cli/azure/cli/command_modules/appservice/tests/latest/test_webapp_commands_thru_mock.py @@ -232,6 +232,44 @@ def test_update_site_config(self, is_centauri_functionapp_mock, site_op_mock): self.assertEqual(site_config.use32_bit_worker_process, None) self.assertEqual(site_config.java_container, None) + @mock.patch('azure.cli.command_modules.appservice.custom._generic_site_operation', autospec=True) + @mock.patch('azure.cli.command_modules.appservice.custom.is_centauri_functionapp', autospec=True) + def test_update_site_config_generic_configurations_camelcase(self, is_centauri_functionapp_mock, site_op_mock): + """Verify that camelCase properties in --generic-configurations (e.g. webJobsEnabled) + are correctly passed to the API via the SiteConfig MutableMapping dict interface, + not silently dropped by setattr (GitHub issue #33823).""" + cmd_mock = _get_test_cmd() + SiteConfig = cmd_mock.get_models('SiteConfig') + site_config = SiteConfig() + site_op_mock.return_value = site_config + + is_centauri_functionapp_mock.return_value = False + # action: pass webJobsEnabled (camelCase, not a named SDK property) via generic_configurations + update_site_configs(cmd_mock, 'myRG', 'myweb', + generic_configurations=['webJobsEnabled=false']) + # assert: the property must be present in the underlying MutableMapping so that + # the SDK includes it in the API request body + self.assertIn('webJobsEnabled', dict(site_config)) + self.assertEqual(site_config['webJobsEnabled'], 'false') + + @mock.patch('azure.cli.command_modules.appservice.custom._generic_site_operation', autospec=True) + @mock.patch('azure.cli.command_modules.appservice.custom.is_centauri_functionapp', autospec=True) + def test_update_site_config_generic_configurations_camelcase_json(self, is_centauri_functionapp_mock, site_op_mock): + """Verify that camelCase properties in --generic-configurations provided as JSON + (e.g. {"webJobsEnabled": false}) are correctly passed to the API.""" + cmd_mock = _get_test_cmd() + SiteConfig = cmd_mock.get_models('SiteConfig') + site_config = SiteConfig() + site_op_mock.return_value = site_config + + is_centauri_functionapp_mock.return_value = False + # action: pass webJobsEnabled as a JSON object + update_site_configs(cmd_mock, 'myRG', 'myweb', + generic_configurations=['{"webJobsEnabled": false}']) + # assert: the property must be in the underlying MutableMapping + self.assertIn('webJobsEnabled', dict(site_config)) + self.assertEqual(site_config['webJobsEnabled'], False) + @mock.patch('azure.cli.command_modules.appservice.custom._generic_site_operation', autospec=True) def test_list_publish_profiles_on_slots(self, site_op_mock): site_op_mock.return_value = [b''] From 22354452e648c9b11966cd58b6c519ed8679ea01 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 1 Aug 2026 02:29:56 +0000 Subject: [PATCH 3/3] fix: remove unused get_json_object import causing pylint W0611 style failure --- src/azure-cli/azure/cli/command_modules/appservice/custom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/appservice/custom.py b/src/azure-cli/azure/cli/command_modules/appservice/custom.py index 3d20c62c747..2ec2e7b785f 100644 --- a/src/azure-cli/azure/cli/command_modules/appservice/custom.py +++ b/src/azure-cli/azure/cli/command_modules/appservice/custom.py @@ -44,7 +44,7 @@ from azure.cli.core.commands.client_factory import get_mgmt_service_client from azure.cli.core.commands import LongRunningOperation from azure.cli.core.commands.progress import IndeterminateProgressBar -from azure.cli.core.util import shell_safe_json_parse, open_page_in_browser, get_json_object, \ +from azure.cli.core.util import shell_safe_json_parse, open_page_in_browser, \ ConfiguredDefaultSetter from azure.cli.core.util import get_az_user_agent, send_raw_request, get_file_json from azure.cli.core.profiles import ResourceType, get_sdk