diff --git a/CHANGELOG.md b/CHANGELOG.md index c0ad10ee89f8..af8b74ec17fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Versions are `MAJOR.PATCH`. ### Deprecated ### Changed +- [#56753](https://github.com/saltstack/salt/pull/56753) - Backport 51095 ### Fixed - [#56237](https://github.com/saltstack/salt/pull/56237) - Fix alphabetical ordering and remove duplicates across all documentation indexes - [@myii](https://github.com/myii) diff --git a/salt/modules/win_timezone.py b/salt/modules/win_timezone.py index 64c1134ef93a..b64aa05c5a17 100644 --- a/salt/modules/win_timezone.py +++ b/salt/modules/win_timezone.py @@ -209,24 +209,22 @@ def get_zone(): Returns: str: Timezone in unix format + Raises: + CommandExecutionError: If timezone could not be gathered + CLI Example: .. code-block:: bash salt '*' timezone.get_zone """ - win_zone = __utils__["reg.read_value"]( - hive="HKLM", - key="SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation", - vname="TimeZoneKeyName", - )["vdata"] - # Some data may have null characters. We only need the first portion up to - # the first null character. See the following: - # https://github.com/saltstack/salt/issues/51940 - # https://stackoverflow.com/questions/27716746/hklm-system-currentcontrolset-control-timezoneinformation-timezonekeyname-corrup - if "\0" in win_zone: - win_zone = win_zone.split("\0")[0] - return mapper.get_unix(win_zone.lower(), "Unknown") + cmd = ["tzutil", "/g"] + res = __salt__["cmd.run_all"](cmd, python_shell=False) + if res["retcode"] or not res["stdout"]: + raise CommandExecutionError( + "tzutil encountered an error getting timezone", info=res + ) + return mapper.get_unix(res["stdout"].lower(), "Unknown") def get_offset(): diff --git a/tests/unit/modules/test_win_timezone.py b/tests/unit/modules/test_win_timezone.py index dfea7b5084f8..8c1ae98fbe61 100644 --- a/tests/unit/modules/test_win_timezone.py +++ b/tests/unit/modules/test_win_timezone.py @@ -7,6 +7,7 @@ # Import Salt Libs import salt.modules.win_timezone as win_timezone +from salt.exceptions import CommandExecutionError # Import Salt Testing Libs from tests.support.mixins import LoaderModuleMockMixin @@ -23,47 +24,62 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin): def setup_loader_modules(self): return {win_timezone: {}} - # 'get_zone' function tests: 3 - - def test_get_zone(self): + def test_get_zone_normal(self): """ - Test if it gets current timezone (i.e. Asia/Calcutta) + Test if it get current timezone (i.e. Asia/Calcutta) """ - mock_read = MagicMock( - side_effect=[ - {"vdata": "India Standard Time"}, - {"vdata": "Indian Standard Time"}, - ] + mock_read_ok = MagicMock( + return_value={ + "pid": 78, + "retcode": 0, + "stderr": "", + "stdout": "India Standard Time", + } ) - - with patch.dict(win_timezone.__utils__, {"reg.read_value": mock_read}): + with patch.dict(win_timezone.__salt__, {"cmd.run_all": mock_read_ok}): self.assertEqual(win_timezone.get_zone(), "Asia/Calcutta") - self.assertEqual(win_timezone.get_zone(), "Unknown") - def test_get_zone_null_terminated(self): + def test_get_zone_unknown(self): """ - Test if it handles instances where the registry contains null values + Test get_zone with unknown timezone (i.e. Indian Standard Time) """ - mock_read = MagicMock( - side_effect=[ - {"vdata": "India Standard Time\0\0\0\0"}, - {"vdata": "Indian Standard Time\0\0some more junk data\0\0"}, - ] + mock_read_error = MagicMock( + return_value={ + "pid": 78, + "retcode": 0, + "stderr": "", + "stdout": "Indian Standard Time", + } ) - - with patch.dict(win_timezone.__utils__, {"reg.read_value": mock_read}): - self.assertEqual(win_timezone.get_zone(), "Asia/Calcutta") + with patch.dict(win_timezone.__salt__, {"cmd.run_all": mock_read_error}): self.assertEqual(win_timezone.get_zone(), "Unknown") + def test_get_zone_error(self): + """ + Test get_zone when it encounters an error + """ + mock_read_fatal = MagicMock( + return_value={"pid": 78, "retcode": 1, "stderr": "", "stdout": ""} + ) + with patch.dict(win_timezone.__salt__, {"cmd.run_all": mock_read_fatal}): + self.assertRaises(CommandExecutionError, win_timezone.get_zone) + # 'get_offset' function tests: 1 def test_get_offset(self): """ Test if it get current numeric timezone offset from UCT (i.e. +0530) """ - mock_read = MagicMock(return_value={"vdata": "India Standard Time"}) + mock_read = MagicMock( + return_value={ + "pid": 78, + "retcode": 0, + "stderr": "", + "stdout": "India Standard Time", + } + ) - with patch.dict(win_timezone.__utils__, {"reg.read_value": mock_read}): + with patch.dict(win_timezone.__salt__, {"cmd.run_all": mock_read}): self.assertEqual(win_timezone.get_offset(), "+0530") # 'get_zonecode' function tests: 1 @@ -72,9 +88,16 @@ def test_get_zonecode(self): """ Test if it get current timezone (i.e. PST, MDT, etc) """ - mock_read = MagicMock(return_value={"vdata": "India Standard Time"}) + mock_read = MagicMock( + return_value={ + "pid": 78, + "retcode": 0, + "stderr": "", + "stdout": "India Standard Time", + } + ) - with patch.dict(win_timezone.__utils__, {"reg.read_value": mock_read}): + with patch.dict(win_timezone.__salt__, {"cmd.run_all": mock_read}): self.assertEqual(win_timezone.get_zonecode(), "IST") # 'set_zone' function tests: 1 @@ -83,13 +106,20 @@ def test_set_zone(self): """ Test if it unlinks, then symlinks /etc/localtime to the set timezone. """ - mock_cmd = MagicMock( + mock_write = MagicMock( return_value={"pid": 78, "retcode": 0, "stderr": "", "stdout": ""} ) - mock_read = MagicMock(return_value={"vdata": "India Standard Time"}) + mock_read = MagicMock( + return_value={ + "pid": 78, + "retcode": 0, + "stderr": "", + "stdout": "India Standard Time", + } + ) - with patch.dict(win_timezone.__salt__, {"cmd.run_all": mock_cmd}), patch.dict( - win_timezone.__utils__, {"reg.read_value": mock_read} + with patch.dict(win_timezone.__salt__, {"cmd.run_all": mock_write}), patch.dict( + win_timezone.__salt__, {"cmd.run_all": mock_read} ): self.assertTrue(win_timezone.set_zone("Asia/Calcutta")) @@ -102,9 +132,16 @@ def test_zone_compare(self): the one set in /etc/localtime. Returns True if they match, and False if not. Mostly useful for running state checks. """ - mock_read = MagicMock(return_value={"vdata": "India Standard Time"}) + mock_read = MagicMock( + return_value={ + "pid": 78, + "retcode": 0, + "stderr": "", + "stdout": "India Standard Time", + } + ) - with patch.dict(win_timezone.__utils__, {"reg.read_value": mock_read}): + with patch.dict(win_timezone.__salt__, {"cmd.run_all": mock_read}): self.assertTrue(win_timezone.zone_compare("Asia/Calcutta")) # 'get_hwclock' function tests: 1