From 0788122499e52584d2fb0de5477b6fa41227b361 Mon Sep 17 00:00:00 2001 From: Shane Lee Date: Mon, 11 Mar 2024 11:21:00 -0600 Subject: [PATCH 1/4] Whitelist package tests for Windows --- tests/conftest.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 8b7ea8056d8..d92bf445211 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -821,11 +821,14 @@ def pytest_runtest_setup(item): entropy_generator.generate_entropy() if salt.utils.platform.is_windows(): - unit_tests_paths = ( + auto_whitelisted_paths = ( str(TESTS_DIR / "unit"), str(PYTESTS_DIR / "unit"), + str(PYTESTS_DIR / "pkg"), ) - if not str(pathlib.Path(item.fspath).resolve()).startswith(unit_tests_paths): + if not str(pathlib.Path(item.fspath).resolve()).startswith( + auto_whitelisted_paths + ): # Unit tests are whitelisted on windows by default, so, we're only # after all other tests windows_whitelisted_marker = item.get_closest_marker("windows_whitelisted") From 559ad14f54f828419771fc67c9b86b084e1f1ef9 Mon Sep 17 00:00:00 2001 From: Shane Lee Date: Thu, 14 Mar 2024 14:31:30 -0600 Subject: [PATCH 2/4] Make the tests run on Windows --- tests/conftest.py | 3 +- tests/support/pkg.py | 73 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index d92bf445211..11510272a52 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -448,8 +448,7 @@ def pytest_collection_modifyitems(config, items): groups_collection_modifyitems(config, items) from_filenames_collection_modifyitems(config, items) - log.warning("Mofifying collected tests to keep track of fixture usage") - + log.warning("Modifying collected tests to keep track of fixture usage") timeout_marker_tests_paths = ( str(PYTESTS_DIR / "pkg"), str(PYTESTS_DIR / "scenarios"), diff --git a/tests/support/pkg.py b/tests/support/pkg.py index 6df2dac0f63..d7e1a75ea28 100644 --- a/tests/support/pkg.py +++ b/tests/support/pkg.py @@ -237,7 +237,7 @@ class SaltPkgInstall: break if not version: pytest.fail( - f"Failed to package artifacts in '{ARTIFACTS_DIR}'. " + f"Failed to find package artifacts in '{ARTIFACTS_DIR}'. " f"Directory Contents:\n{pprint.pformat(artifacts)}" ) return version @@ -295,6 +295,10 @@ class SaltPkgInstall: self.run_root = self.bin_dir / "run" else: log.error("Unexpected file extension: %s", self.file_ext) + log.debug("root: %s", self.root) + log.debug("bin_dir: %s", self.bin_dir) + log.debug("ssm_bin: %s", self.ssm_bin) + log.debug("run_root: %s", self.run_root) if not self.pkgs: pytest.fail("Could not find Salt Artifacts") @@ -400,6 +404,9 @@ class SaltPkgInstall: self.binary_paths["spm"] = [shutil.which("salt-spm")] else: self.binary_paths["pip"] = [shutil.which("salt-pip")] + log.debug("python_bin: %s", python_bin) + log.debug("binary_paths: %s", self.binary_paths) + log.debug("install_dir: %s", self.install_dir) @staticmethod def salt_factories_root_dir(system_service: bool = False) -> pathlib.Path: @@ -413,8 +420,8 @@ class SaltPkgInstall: def _check_retcode(self, ret): """ - helper function ot check subprocess.run - returncode equals 0, if not raise assertionerror + Helper function to check subprocess.run returncode equals 0 + If not raise AssertionError """ if ret.returncode != 0: log.error(ret) @@ -462,8 +469,14 @@ class SaltPkgInstall: # Remove the service installed by the installer log.debug("Removing installed salt-minion service") self.proc.run(str(self.ssm_bin), "remove", "salt-minion", "confirm") + + # Add installation to the path self.update_process_path() + # Install the service using our config + if self.pkg_system_service: + self._install_ssm_service() + elif platform.is_darwin(): daemons_dir = pathlib.Path("/Library", "LaunchDaemons") service_name = "com.saltstack.salt.minion" @@ -510,6 +523,54 @@ class SaltPkgInstall: log.info(ret) self._check_retcode(ret) + def _install_ssm_service(self, service="minion"): + """ + This function installs the service on Windows using SSM but does not + start it. + + Args: + + service (str): + The name of the service. Default is ``minion`` + """ + service_name = f"salt-{service}" + binary = self.install_dir / f"{service_name}.exe" + ret = self.proc.run( + str(self.ssm_bin), + "install", + service_name, + binary, + "-c", + f'"{str(self.conf_dir)}"', + ) + self._check_retcode(ret) + ret = self.proc.run( + str(self.ssm_bin), + "set", + service_name, + "Description", + "Salt Minion for testing", + ) + self._check_retcode(ret) + # This doesn't start the service. It will start automatically on reboot + # It is set here to make it the same as what the installer does + ret = self.proc.run( + str(self.ssm_bin), "set", service_name, "Start", "SERVICE_AUTO_START" + ) + self._check_retcode(ret) + ret = self.proc.run( + str(self.ssm_bin), "set", service_name, "AppStopMethodConsole", "24000" + ) + self._check_retcode(ret) + ret = self.proc.run( + str(self.ssm_bin), "set", service_name, "AppStopMethodWindow", "2000" + ) + self._check_retcode(ret) + ret = self.proc.run( + str(self.ssm_bin), "set", service_name, "AppRestartDelay", "60000" + ) + self._check_retcode(ret) + def package_python_version(self): return self.proc.run( str(self.binary_paths["python"][0]), @@ -762,7 +823,7 @@ class SaltPkgInstall: self._check_retcode(ret) if self.pkg_system_service: - self._install_system_service() + self._install_ssm_service() elif platform.is_darwin(): if self.classic: @@ -1229,8 +1290,8 @@ class PkgSsmSaltDaemonImpl(PkgSystemdSaltDaemonImpl): # Dereference the internal _process attribute self._process = None - # Lets log and kill any child processes left behind, including the main subprocess - # if it failed to properly stop + # Let's log and kill any child processes left behind, including the main + # subprocess if it failed to properly stop terminate_process( pid=pid, kill_children=True, From 293f6b2d02688c96bf89ed4ffcf9e0cf1b7b3c8a Mon Sep 17 00:00:00 2001 From: Shane Lee Date: Fri, 15 Mar 2024 08:46:26 -0600 Subject: [PATCH 3/4] Skip state test on Windows --- tests/pytests/pkg/download/test_pkg_download.py | 2 +- tests/pytests/pkg/integration/test_salt_state_file.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/pytests/pkg/download/test_pkg_download.py b/tests/pytests/pkg/download/test_pkg_download.py index b774d9fa047..9a0fbd76bad 100644 --- a/tests/pytests/pkg/download/test_pkg_download.py +++ b/tests/pytests/pkg/download/test_pkg_download.py @@ -464,7 +464,7 @@ def setup_windows( try: arch = os.environ.get("SALT_REPO_ARCH") or "amd64" if package_type != "onedir": - root_dir = pathlib.Path(r"C:\Program Files\Salt Project\Salt") + root_dir = pathlib.Path(os.getenv("ProgramFiles"), "Salt Project", "Salt") if packaging.version.parse(salt_release) > packaging.version.parse("3005"): if package_type.lower() == "nsis": diff --git a/tests/pytests/pkg/integration/test_salt_state_file.py b/tests/pytests/pkg/integration/test_salt_state_file.py index 7b71fcb2365..1aadf3dbddb 100644 --- a/tests/pytests/pkg/integration/test_salt_state_file.py +++ b/tests/pytests/pkg/integration/test_salt_state_file.py @@ -5,6 +5,10 @@ import pytest from pytestskipmarkers.utils import platform from saltfactories.utils.functional import MultiStateResult +pytestmark = [ + pytest.mark.skip_on_windows, +] + @pytest.fixture def files(tmp_path): From 35bc5fc46b0f90891363d84a2062a0d7c875c50a Mon Sep 17 00:00:00 2001 From: Shane Lee Date: Fri, 15 Mar 2024 09:02:41 -0600 Subject: [PATCH 4/4] Revert weird change --- tests/support/pkg.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/support/pkg.py b/tests/support/pkg.py index d7e1a75ea28..e01bebc7594 100644 --- a/tests/support/pkg.py +++ b/tests/support/pkg.py @@ -199,7 +199,7 @@ class SaltPkgInstall: Default location for salt configurations """ if platform.is_windows(): - config_path = pathlib.Path("C://salt", "etc", "salt") + config_path = pathlib.Path("C:\\salt", "etc", "salt") else: config_path = pathlib.Path("/etc", "salt") return config_path @@ -413,7 +413,7 @@ class SaltPkgInstall: if system_service is False: return None if platform.is_windows(): - return pathlib.Path("C:/salt") + return pathlib.Path("C:\\salt") if platform.is_darwin(): return pathlib.Path("/opt/salt") return pathlib.Path("/")