diff --git a/salt/utils/cloud.py b/salt/utils/cloud.py index 79389ea8a9c7..a6293181a446 100644 --- a/salt/utils/cloud.py +++ b/salt/utils/cloud.py @@ -80,9 +80,11 @@ import importlib import importlib.metadata - # Verify WinRM 0.3.0 or greater + # Verify WinRM 0.3.0 or greater. The PyPI distribution is "pywinrm" + # (imported as `winrm`); looking up "winrm" raises PackageNotFoundError + # (an ImportError subclass), leaving HAS_WINRM always False. See #69976. - version = importlib.metadata.version("winrm") + version = importlib.metadata.version("pywinrm") if not salt.utils.versions.compare(version, ">=", WINRM_MIN_VER): HAS_WINRM = False else: diff --git a/tests/pytests/unit/utils/test_cloud.py b/tests/pytests/unit/utils/test_cloud.py index 4dfe796b2bb9..8c148846dbef 100644 --- a/tests/pytests/unit/utils/test_cloud.py +++ b/tests/pytests/unit/utils/test_cloud.py @@ -561,6 +561,23 @@ def test_winrm_pinnned_version(): assert winrm_version >= "0.3.0" +def test_has_winrm_detection_uses_pywinrm_distribution(): + """ + HAS_WINRM must be detected via the "pywinrm" distribution name (the PyPI + package), not "winrm". ``importlib.metadata.version("winrm")`` raises + ``PackageNotFoundError`` (an ``ImportError`` subclass), which the surrounding + ``except ImportError`` swallows, leaving ``HAS_WINRM`` always ``False`` and + breaking salt-cloud WinRM deployments. See #69976. + """ + import importlib.metadata + + try: + importlib.metadata.version("pywinrm") + except importlib.metadata.PackageNotFoundError: + pytest.skip("pywinrm is not installed in this env.") + assert cloud.HAS_WINRM is True + + def test_ssh_gateway_arguments_default_alive_args(): server_alive_interval = 60 server_alive_count_max = 3