From 0d78611767b48aa0e145fa2e0a3a83c2de067d91 Mon Sep 17 00:00:00 2001 From: Shane Lee Date: Tue, 23 Jul 2024 12:02:10 -0600 Subject: [PATCH] Fix win_wua to handle empty CDispatch objects --- changelog/66718.fixed.md | 2 ++ salt/utils/win_update.py | 16 +++++---- tests/pytests/unit/utils/test_win_update.py | 38 +++++++++++++++++++++ 3 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 changelog/66718.fixed.md diff --git a/changelog/66718.fixed.md b/changelog/66718.fixed.md new file mode 100644 index 00000000000..8a4a15ebad4 --- /dev/null +++ b/changelog/66718.fixed.md @@ -0,0 +1,2 @@ +Fixed ``win_wua.available`` when some of the update objects are empty CDispatch +objects. The ``available`` function no longer crashes diff --git a/salt/utils/win_update.py b/salt/utils/win_update.py index dd54f213963..1c93c5b18ea 100644 --- a/salt/utils/win_update.py +++ b/salt/utils/win_update.py @@ -528,14 +528,18 @@ class WindowsUpdateAgent: found = updates.updates for update in self._updates: + # Some update objects seem to be empty or undefined. Those will be + # exposed here if they are missing these attributes + try: + if salt.utils.data.is_true(update.IsHidden) and skip_hidden: + continue - if salt.utils.data.is_true(update.IsHidden) and skip_hidden: - continue + if salt.utils.data.is_true(update.IsInstalled) and skip_installed: + continue - if salt.utils.data.is_true(update.IsInstalled) and skip_installed: - continue - - if salt.utils.data.is_true(update.IsMandatory) and skip_mandatory: + if salt.utils.data.is_true(update.IsMandatory) and skip_mandatory: + continue + except AttributeError: continue # Windows 10 build 2004 introduced some problems with the diff --git a/tests/pytests/unit/utils/test_win_update.py b/tests/pytests/unit/utils/test_win_update.py index a221ee31952..9939428c7ca 100644 --- a/tests/pytests/unit/utils/test_win_update.py +++ b/tests/pytests/unit/utils/test_win_update.py @@ -1,14 +1,52 @@ import pytest +try: + import win32com.client + + HAS_WIN32 = True +except ImportError: + HAS_WIN32 = False + import salt.utils.win_update as win_update from tests.support.mock import MagicMock, patch pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.skipif(not HAS_WIN32, reason="Requires Win32 libraries"), ] +def test_available_no_updates(): + """ + Test installed when there are no updates on the system + """ + with patch("salt.utils.winapi.Com", autospec=True), patch( + "win32com.client.Dispatch", autospec=True + ), patch.object(win_update.WindowsUpdateAgent, "refresh", autospec=True): + wua = win_update.WindowsUpdateAgent(online=False) + wua._updates = [] + + available_updates = wua.available() + + assert available_updates.updates.Add.call_count == 0 + + +def test_available_no_updates_empty_objects(): + """ + Test installed when there are no updates on the system + """ + with patch("salt.utils.winapi.Com", autospec=True), patch( + "win32com.client.Dispatch", autospec=True + ), patch.object(win_update.WindowsUpdateAgent, "refresh", autospec=True): + wua = win_update.WindowsUpdateAgent(online=False) + wua._updates = [win32com.client.CDispatch, win32com.client.CDispatch] + + available_updates = wua.available() + + assert available_updates.updates.Add.call_count == 0 + + def test_installed_no_updates(): """ Test installed when there are no updates on the system