From ae80dcddae6649a4ee031e76314aac23f3325d54 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Fri, 21 Jul 2023 10:56:25 +0100 Subject: [PATCH] Reduce code duplication Signed-off-by: Pedro Algarvio --- tests/pytests/functional/formulas/conftest.py | 16 +++++++ .../functional/formulas/test_docker.py | 41 +++-------------- .../pytests/functional/formulas/test_nginx.py | 41 +++-------------- .../pytests/functional/formulas/test_salt.py | 40 +++-------------- .../pytests/functional/formulas/test_users.py | 40 +++-------------- tests/support/helpers.py | 13 ++++++ tests/support/pytest/formulas.py | 44 +++++++++++++++++++ 7 files changed, 101 insertions(+), 134 deletions(-) create mode 100644 tests/pytests/functional/formulas/conftest.py create mode 100644 tests/support/pytest/formulas.py diff --git a/tests/pytests/functional/formulas/conftest.py b/tests/pytests/functional/formulas/conftest.py new file mode 100644 index 00000000000..33d5ec40fb6 --- /dev/null +++ b/tests/pytests/functional/formulas/conftest.py @@ -0,0 +1,16 @@ +import shutil + +import pytest + +from tests.support.pytest.formulas import SaltStackFormula + + +@pytest.fixture(scope="module") +def saltstack_formula(tmp_path_factory, base_env_state_tree_root_dir): + zipfiles_dir = tmp_path_factory.mktemp("fomulas-zips") + try: + yield SaltStackFormula.with_default_paths( + zipfiles_dir, base_env_state_tree_root_dir + ) + finally: + shutil.rmtree(zipfiles_dir, ignore_errors=True) diff --git a/tests/pytests/functional/formulas/test_docker.py b/tests/pytests/functional/formulas/test_docker.py index 367f96e91fc..76f97ffcaab 100644 --- a/tests/pytests/functional/formulas/test_docker.py +++ b/tests/pytests/functional/formulas/test_docker.py @@ -1,47 +1,20 @@ """ Tests using docker formula """ -import shutil -from pathlib import Path -from zipfile import ZipFile - import pytest -import requests - -import salt.utils.files @pytest.fixture(scope="module") -def modules(loaders): +def _formula(saltstack_formula): + with saltstack_formula(name="docker-formula", tag="2.4.2") as formula: + yield formula + + +@pytest.fixture(scope="module") +def modules(loaders, _formula): return loaders.modules -@pytest.fixture(scope="module") -def formula_tag(): - return "2.4.2" - - -@pytest.fixture(scope="module") -def repo_url(formula_tag): - return f"https://github.com/saltstack-formulas/docker-formula/archive/refs/tags/v{formula_tag}.zip" - - -@pytest.fixture(scope="module", autouse=True) -def docker_repo(state_tree, base_env_state_tree_root_dir, formula_tag, repo_url): - local_filename = Path(repo_url.split("/")[-1]) - zip_path = state_tree / local_filename - with requests.get(repo_url, allow_redirects=True, stream=True) as req: - req.raise_for_status() - with salt.utils.files.fopen(zip_path, "wb") as fho: - for chunk in req.iter_content(chunk_size=8192): - fho.write(chunk) - with ZipFile(zip_path) as zip_obj: - zip_obj.extractall(state_tree) - extract_path = state_tree / f"docker-formula-{formula_tag}" - shutil.move(extract_path / "docker", base_env_state_tree_root_dir) - return str(base_env_state_tree_root_dir) - - def test_docker_formula(modules): ret = modules.state.sls("docker", test=True) for staterun in ret: diff --git a/tests/pytests/functional/formulas/test_nginx.py b/tests/pytests/functional/formulas/test_nginx.py index 7adfd6af44f..ef8f6655fbf 100644 --- a/tests/pytests/functional/formulas/test_nginx.py +++ b/tests/pytests/functional/formulas/test_nginx.py @@ -1,47 +1,20 @@ """ Tests using nginx formula """ -import shutil -from pathlib import Path -from zipfile import ZipFile - import pytest -import requests - -import salt.utils.files @pytest.fixture(scope="module") -def modules(loaders): +def _formula(saltstack_formula): + with saltstack_formula(name="nginx-formula", tag="2.8.1") as formula: + yield formula + + +@pytest.fixture(scope="module") +def modules(loaders, _formula): return loaders.modules -@pytest.fixture(scope="module") -def formula_tag(): - return "2.8.1" - - -@pytest.fixture(scope="module") -def repo_url(formula_tag): - return f"https://github.com/saltstack-formulas/nginx-formula/archive/refs/tags/v{formula_tag}.zip" - - -@pytest.fixture(scope="module", autouse=True) -def nginx_repo(state_tree, base_env_state_tree_root_dir, formula_tag, repo_url): - local_filename = Path(repo_url.split("/")[-1]) - zip_path = state_tree / local_filename - with requests.get(repo_url, allow_redirects=True, stream=True) as req: - req.raise_for_status() - with salt.utils.files.fopen(zip_path, "wb") as fho: - for chunk in req.iter_content(chunk_size=8192): - fho.write(chunk) - with ZipFile(zip_path) as zip_obj: - zip_obj.extractall(state_tree) - extract_path = state_tree / f"nginx-formula-{formula_tag}" - shutil.move(extract_path / "nginx", base_env_state_tree_root_dir) - return str(base_env_state_tree_root_dir) - - def test_formula(modules): ret = modules.state.sls("nginx", test=True) for staterun in ret: diff --git a/tests/pytests/functional/formulas/test_salt.py b/tests/pytests/functional/formulas/test_salt.py index d1f8fa7b2c7..5b32bd121ad 100644 --- a/tests/pytests/functional/formulas/test_salt.py +++ b/tests/pytests/functional/formulas/test_salt.py @@ -1,47 +1,21 @@ """ Tests using salt formula """ -import shutil -from pathlib import Path -from zipfile import ZipFile import pytest -import requests - -import salt.utils.files @pytest.fixture(scope="module") -def modules(loaders): +def _formula(saltstack_formula): + with saltstack_formula(name="salt-formula", tag="1.12.0") as formula: + yield formula + + +@pytest.fixture(scope="module") +def modules(loaders, _formula): return loaders.modules -@pytest.fixture(scope="module") -def formula_tag(): - return "1.12.0" - - -@pytest.fixture(scope="module") -def repo_url(formula_tag): - return f"https://github.com/saltstack-formulas/salt-formula/archive/refs/tags/v{formula_tag}.zip" - - -@pytest.fixture(scope="module", autouse=True) -def salt_repo(state_tree, base_env_state_tree_root_dir, formula_tag, repo_url): - local_filename = Path(repo_url.split("/")[-1]) - zip_path = state_tree / local_filename - with requests.get(repo_url, allow_redirects=True, stream=True) as req: - req.raise_for_status() - with salt.utils.files.fopen(zip_path, "wb") as fho: - for chunk in req.iter_content(chunk_size=8192): - fho.write(chunk) - with ZipFile(zip_path) as zip_obj: - zip_obj.extractall(state_tree) - extract_path = state_tree / f"salt-formula-{formula_tag}" - shutil.move(extract_path / "salt", base_env_state_tree_root_dir) - return str(base_env_state_tree_root_dir) - - def test_salt_formula(modules): # Master Formula ret = modules.state.sls("salt.master", test=True) diff --git a/tests/pytests/functional/formulas/test_users.py b/tests/pytests/functional/formulas/test_users.py index d6765a16c0d..80b4fa29698 100644 --- a/tests/pytests/functional/formulas/test_users.py +++ b/tests/pytests/functional/formulas/test_users.py @@ -1,47 +1,21 @@ """ Tests using users formula """ -import shutil -from pathlib import Path -from zipfile import ZipFile import pytest -import requests - -import salt.utils.files @pytest.fixture(scope="module") -def modules(loaders): +def _formula(saltstack_formula): + with saltstack_formula(name="users-formula", tag="0.48.8") as formula: + yield formula + + +@pytest.fixture(scope="module") +def modules(loaders, _formula): return loaders.modules -@pytest.fixture(scope="module") -def formula_tag(): - return "0.48.8" - - -@pytest.fixture(scope="module") -def repo_url(formula_tag): - return f"https://github.com/saltstack-formulas/users-formula/archive/refs/tags/v{formula_tag}.zip" - - -@pytest.fixture(scope="module", autouse=True) -def users_repo(state_tree, base_env_state_tree_root_dir, formula_tag, repo_url): - local_filename = Path(repo_url.split("/")[-1]) - zip_path = state_tree / local_filename - with requests.get(repo_url, allow_redirects=True, stream=True) as req: - req.raise_for_status() - with salt.utils.files.fopen(zip_path, "wb") as fho: - for chunk in req.iter_content(chunk_size=8192): - fho.write(chunk) - with ZipFile(zip_path) as zip_obj: - zip_obj.extractall(state_tree) - extract_path = state_tree / f"users-formula-{formula_tag}" - shutil.move(extract_path / "users", base_env_state_tree_root_dir) - return str(base_env_state_tree_root_dir) - - def test_users_formula(modules): # sudo ret = modules.state.sls("users.sudo", test=True) diff --git a/tests/support/helpers.py b/tests/support/helpers.py index d8b7f2915f8..9988ab8e817 100644 --- a/tests/support/helpers.py +++ b/tests/support/helpers.py @@ -34,6 +34,7 @@ import types import attr import pytest +import requests import tornado.ioloop import tornado.web from pytestshellutils.exceptions import ProcessFailed @@ -1896,3 +1897,15 @@ class Keys: def __exit__(self, *_): shutil.rmtree(str(self.priv_path.parent), ignore_errors=True) + + +@pytest.helpers.register +def download_file(url, dest, auth=None): + # NOTE the stream=True parameter below + with requests.get(url, allow_redirects=True, stream=True, auth=auth) as r: + r.raise_for_status() + with salt.utils.files.fopen(dest, "wb") as f: + for chunk in r.iter_content(chunk_size=8192): + if chunk: + f.write(chunk) + return dest diff --git a/tests/support/pytest/formulas.py b/tests/support/pytest/formulas.py new file mode 100644 index 00000000000..bed0b95f888 --- /dev/null +++ b/tests/support/pytest/formulas.py @@ -0,0 +1,44 @@ +import functools +import pathlib +import shutil +import zipfile + +import attr +import pytest + + +@attr.s(slots=True, frozen=True) +class SaltStackFormula: + """ + Class representing a saltstack formula. + """ + + name: str = attr.ib() + tag: str = attr.ib() + tmp_path: pathlib.Path = attr.ib() + state_tree_path: pathlib.Path = attr.ib() + url: str = attr.ib() + + @url.default + def _default_url(self): + return f"https://github.com/saltstack-formulas/{self.name}/archive/refs/tags/v{self.tag}.zip" + + def __enter__(self): + target_path = self.state_tree_path / f"{self.name}-{self.tag}" + if not target_path.exists(): + zipfile_path = pytest.helpers.download_file( + self.url, self.tmp_path / self.url.split("/")[-1] + ) + with zipfile.ZipFile(zipfile_path) as zip_obj: + zip_obj.extractall(self.tmp_path) + shutil.move(self.tmp_path / f"{self.name}-{self.tag}", target_path) + return self + + def __exit__(self, *_): + pass + + @classmethod + def with_default_paths(cls, tmp_path, state_tree_path): + return functools.partial( + cls, tmp_path=tmp_path, state_tree_path=state_tree_path + )