From 2cbec8785d6cdda3cb9139bf396b543dc35f7b3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ma=CC=88der?= Date: Tue, 28 Jul 2026 14:52:59 +0200 Subject: [PATCH 1/3] Fix crash for `containerapp job update --no-wait` --- src/azure-cli/azure/cli/command_modules/containerapp/custom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/containerapp/custom.py b/src/azure-cli/azure/cli/command_modules/containerapp/custom.py index 4e8c66e4dac..8c479bded7e 100644 --- a/src/azure-cli/azure/cli/command_modules/containerapp/custom.py +++ b/src/azure-cli/azure/cli/command_modules/containerapp/custom.py @@ -1443,7 +1443,7 @@ def update_containerappsjob_logic(cmd, r = ContainerAppsJobClient.update( cmd=cmd, resource_group_name=resource_group_name, name=name, containerapp_job_envelope=new_containerappsjob, no_wait=no_wait) - if "properties" in r and "provisioningState" in r["properties"] and r["properties"]["provisioningState"].lower() == "waiting" and not no_wait: + if not no_wait and "properties" in r and "provisioningState" in r["properties"] and r["properties"]["provisioningState"].lower() == "waiting": logger.warning('Containerapps job update in progress. Please monitor the update using `az containerapp job show -n {} -g {}`'.format(name, resource_group_name)) return r From af248d622726bddbabdfa18eec9337afab5073ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ma=CC=88der?= Date: Tue, 28 Jul 2026 15:24:15 +0200 Subject: [PATCH 2/3] Add regression tests --- ..._containerapp_update_provisioning_state.py | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/azure-cli/azure/cli/command_modules/containerapp/tests/latest/test_containerapp_update_provisioning_state.py diff --git a/src/azure-cli/azure/cli/command_modules/containerapp/tests/latest/test_containerapp_update_provisioning_state.py b/src/azure-cli/azure/cli/command_modules/containerapp/tests/latest/test_containerapp_update_provisioning_state.py new file mode 100644 index 00000000000..eff8b125f5a --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/containerapp/tests/latest/test_containerapp_update_provisioning_state.py @@ -0,0 +1,70 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) nxt Engineering GmbH. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- +import unittest +from unittest import mock + +from azure.cli.command_modules.containerapp.custom import ( + ContainerAppClient, + ContainerAppsJobClient, + update_containerapp_logic, + update_containerappsjob_logic, +) + +# flake8: noqa +# noqa +# pylint: skip-file + + +# `ContainerAppClient.update`/`ContainerAppsJobClient.update` return None when no_wait=True, +# so the post-update provisioningState check must short-circuit on `not no_wait` before +# indexing into that None result. +class UpdateProvisioningStateCheckTest(unittest.TestCase): + @mock.patch("azure.cli.command_modules.containerapp.custom._validate_subscription_registered") + @mock.patch.object(ContainerAppClient, "update", return_value=None) + @mock.patch.object(ContainerAppClient, "show", return_value={"properties": {}}) + def test_containerapp_update_no_wait_does_not_raise(self, _show_mock, _update_mock, _validate_mock): + cmd = mock.MagicMock() + + result = update_containerapp_logic( + cmd=cmd, name="app1", resource_group_name="rg1", no_wait=True) + + self.assertIsNone(result) + + @mock.patch("azure.cli.command_modules.containerapp.custom._validate_subscription_registered") + @mock.patch.object(ContainerAppsJobClient, "update", return_value=None) + @mock.patch.object(ContainerAppsJobClient, "show", return_value={"properties": {}}) + def test_containerappjob_update_no_wait_does_not_raise(self, _show_mock, _update_mock, _validate_mock): + cmd = mock.MagicMock() + + result = update_containerappsjob_logic( + cmd=cmd, name="job1", resource_group_name="rg1", no_wait=True) + + self.assertIsNone(result) + + @mock.patch("azure.cli.command_modules.containerapp.custom._validate_subscription_registered") + @mock.patch.object(ContainerAppClient, "update", return_value={"properties": {"provisioningState": "Waiting"}}) + @mock.patch.object(ContainerAppClient, "show", return_value={"properties": {}}) + def test_containerapp_update_without_no_wait_returns_response(self, _show_mock, update_mock, _validate_mock): + cmd = mock.MagicMock() + + result = update_containerapp_logic( + cmd=cmd, name="app1", resource_group_name="rg1", no_wait=False) + + self.assertEqual(result, update_mock.return_value) + + @mock.patch("azure.cli.command_modules.containerapp.custom._validate_subscription_registered") + @mock.patch.object(ContainerAppsJobClient, "update", return_value={"properties": {"provisioningState": "Waiting"}}) + @mock.patch.object(ContainerAppsJobClient, "show", return_value={"properties": {}}) + def test_containerappjob_update_without_no_wait_returns_response(self, _show_mock, update_mock, _validate_mock): + cmd = mock.MagicMock() + + result = update_containerappsjob_logic( + cmd=cmd, name="job1", resource_group_name="rg1", no_wait=False) + + self.assertEqual(result, update_mock.return_value) + + +if __name__ == "__main__": + unittest.main() From eb69964683b307cc8b8d9e0cca3db84f454dd2e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ma=CC=88der?= Date: Tue, 18 Aug 2026 14:06:42 +0200 Subject: [PATCH 3/3] Remove test since because MS doesn't want foreign copyrighted code in there MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … which contradicts with Swiss copyright law. --- ..._containerapp_update_provisioning_state.py | 70 ------------------- 1 file changed, 70 deletions(-) delete mode 100644 src/azure-cli/azure/cli/command_modules/containerapp/tests/latest/test_containerapp_update_provisioning_state.py diff --git a/src/azure-cli/azure/cli/command_modules/containerapp/tests/latest/test_containerapp_update_provisioning_state.py b/src/azure-cli/azure/cli/command_modules/containerapp/tests/latest/test_containerapp_update_provisioning_state.py deleted file mode 100644 index eff8b125f5a..00000000000 --- a/src/azure-cli/azure/cli/command_modules/containerapp/tests/latest/test_containerapp_update_provisioning_state.py +++ /dev/null @@ -1,70 +0,0 @@ -# -------------------------------------------------------------------------------------------- -# Copyright (c) nxt Engineering GmbH. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# -------------------------------------------------------------------------------------------- -import unittest -from unittest import mock - -from azure.cli.command_modules.containerapp.custom import ( - ContainerAppClient, - ContainerAppsJobClient, - update_containerapp_logic, - update_containerappsjob_logic, -) - -# flake8: noqa -# noqa -# pylint: skip-file - - -# `ContainerAppClient.update`/`ContainerAppsJobClient.update` return None when no_wait=True, -# so the post-update provisioningState check must short-circuit on `not no_wait` before -# indexing into that None result. -class UpdateProvisioningStateCheckTest(unittest.TestCase): - @mock.patch("azure.cli.command_modules.containerapp.custom._validate_subscription_registered") - @mock.patch.object(ContainerAppClient, "update", return_value=None) - @mock.patch.object(ContainerAppClient, "show", return_value={"properties": {}}) - def test_containerapp_update_no_wait_does_not_raise(self, _show_mock, _update_mock, _validate_mock): - cmd = mock.MagicMock() - - result = update_containerapp_logic( - cmd=cmd, name="app1", resource_group_name="rg1", no_wait=True) - - self.assertIsNone(result) - - @mock.patch("azure.cli.command_modules.containerapp.custom._validate_subscription_registered") - @mock.patch.object(ContainerAppsJobClient, "update", return_value=None) - @mock.patch.object(ContainerAppsJobClient, "show", return_value={"properties": {}}) - def test_containerappjob_update_no_wait_does_not_raise(self, _show_mock, _update_mock, _validate_mock): - cmd = mock.MagicMock() - - result = update_containerappsjob_logic( - cmd=cmd, name="job1", resource_group_name="rg1", no_wait=True) - - self.assertIsNone(result) - - @mock.patch("azure.cli.command_modules.containerapp.custom._validate_subscription_registered") - @mock.patch.object(ContainerAppClient, "update", return_value={"properties": {"provisioningState": "Waiting"}}) - @mock.patch.object(ContainerAppClient, "show", return_value={"properties": {}}) - def test_containerapp_update_without_no_wait_returns_response(self, _show_mock, update_mock, _validate_mock): - cmd = mock.MagicMock() - - result = update_containerapp_logic( - cmd=cmd, name="app1", resource_group_name="rg1", no_wait=False) - - self.assertEqual(result, update_mock.return_value) - - @mock.patch("azure.cli.command_modules.containerapp.custom._validate_subscription_registered") - @mock.patch.object(ContainerAppsJobClient, "update", return_value={"properties": {"provisioningState": "Waiting"}}) - @mock.patch.object(ContainerAppsJobClient, "show", return_value={"properties": {}}) - def test_containerappjob_update_without_no_wait_returns_response(self, _show_mock, update_mock, _validate_mock): - cmd = mock.MagicMock() - - result = update_containerappsjob_logic( - cmd=cmd, name="job1", resource_group_name="rg1", no_wait=False) - - self.assertEqual(result, update_mock.return_value) - - -if __name__ == "__main__": - unittest.main()