From d2ad1b467fef772079dc06fcdc07a80226398971 Mon Sep 17 00:00:00 2001 From: Matthias Dellweg Date: Wed, 29 Jan 2025 16:46:06 +0100 Subject: [PATCH 1/3] Rewrite collection search tests --- .../v3/test_collection_version_search.py | 598 ++++++++---------- 1 file changed, 251 insertions(+), 347 deletions(-) diff --git a/pulp_ansible/tests/functional/api/collection/v3/test_collection_version_search.py b/pulp_ansible/tests/functional/api/collection/v3/test_collection_version_search.py index 9fbd6dcd0..ccbec12dd 100644 --- a/pulp_ansible/tests/functional/api/collection/v3/test_collection_version_search.py +++ b/pulp_ansible/tests/functional/api/collection/v3/test_collection_version_search.py @@ -1,6 +1,4 @@ import copy -import pickle -import logging import os import random import uuid @@ -8,7 +6,6 @@ import pytest -from pulp_smash.pulp3.bindings import delete_orphans from pulp_ansible.tests.functional.utils import ( gen_distribution, gen_remote, @@ -17,7 +14,14 @@ ) -logger = logging.getLogger(__name__) +# We need to cary a copy of this fixture with extended scope for now. Regret... +@pytest.fixture(scope="session") +def ascii_armored_detached_signing_service( + _ascii_armored_detached_signing_service_name, pulpcore_bindings +): + return pulpcore_bindings.SigningServicesApi.list( + name=_ascii_armored_detached_signing_service_name + ).results[0] REPO_SPECS = { @@ -207,10 +211,6 @@ def keys_from_client_results(results): return sorted(keys) -def keys_from_results(specs): - return keys_from_client_results(specs) - - def compare_keys(a, b): result = "" a_missing = [] @@ -395,20 +395,6 @@ def get_collection_versions(ansible_bindings): return dict(((x.namespace, x.name, x.version), x.to_dict()) for x in cversions.results) -def get_repositories(xclient): - repos = {} - for repo in xclient.list().results: - repos[repo.name] = repo.to_dict() - return repos - - -def get_distributions(xclient): - dists = {} - for dist in xclient.list().results: - dists[dist.name] = dist.to_dict() - return dists - - def client_results_to_dict(results): rmap = {} for result in results: @@ -416,7 +402,7 @@ def client_results_to_dict(results): return rmap -def delete_repos_and_distros(ansible_bindings, reponames=None): +def delete_repos_and_distros(pulpcore_bindings, ansible_bindings, monitor_task, reponames=None): # map out existing distros dists = client_results_to_dict( ansible_bindings.DistributionsAnsibleApi.list(limit=1000).results @@ -437,7 +423,7 @@ def delete_repos_and_distros(ansible_bindings, reponames=None): ansible_bindings.RepositoriesAnsibleApi.delete(repos[rname]["pulp_href"]) # cv's and artifacts should be orphaned if the repos are gone ... - delete_orphans() + monitor_task(pulpcore_bindings.OrphansCleanupApi.cleanup({"protection_time": 0}).task) def create_repos_and_dists( @@ -459,7 +445,6 @@ def create_repos_and_dists( if repo_specs.get(spec["repository_name"], {}).get("pulp_labels"): repo_data["pulp_labels"] = repo_specs[spec["repository_name"]]["pulp_labels"] - # pulp_repo = ansible_bindings.RepositoriesAnsibleApi.create(repo_data) pulp_repo = gen_object_with_cleanup(ansible_bindings.RepositoriesAnsibleApi, repo_data) created_repos[pulp_repo.name] = pulp_repo.to_dict() @@ -477,240 +462,204 @@ def create_repos_and_dists( base_path=pulp_repo.name, repository=pulp_repo.pulp_href, ) - # res = monitor_task(ansible_bindings.DistributionsAnsibleApi.create(dist_data).task) - # dist = ansible_bindings.DistributionsAnsibleApi.read(res.created_resources[0]) dist = gen_object_with_cleanup(ansible_bindings.DistributionsAnsibleApi, dist_data) created_dists[dist.name] = dist.to_dict() return created_dists, created_repos -@pytest.fixture() +@pytest.fixture(scope="class") def search_specs( + pulpcore_bindings, ansible_bindings, ansible_collection_factory, - tmp_path, signing_gpg_homedir_path, ascii_armored_detached_signing_service, monitor_task, gen_object_with_cleanup, ): - repo_specs = copy.deepcopy(REPO_SPECS) + repo_specs = REPO_SPECS specs = copy.deepcopy(SPECS) - new_specs = None - cachefile = os.path.join("/tmp", "xrepo_cache.pickle") + # define signing service + signing_service = ascii_armored_detached_signing_service + signing_body = {"signing_service": signing_service.pulp_href, "content_units": ["*"]} - # if os.path.exists(cachefile): - # os.remove(cachefile) + # make a place to store artifacts in between runs ... + # artifact_cache = os.path.join(tmp_path, "artifacts") + artifact_cache = os.path.join("/tmp", "artifacts") + if not os.path.exists(artifact_cache): + os.makedirs(artifact_cache) - if not os.path.exists(cachefile): - # define signing service - signing_service = ascii_armored_detached_signing_service - signing_body = {"signing_service": signing_service.pulp_href, "content_units": ["*"]} + reponames = sorted(set([x["repository_name"] for x in specs])) - # make a place to store artifacts in between runs ... - # artifact_cache = os.path.join(tmp_path, "artifacts") - artifact_cache = os.path.join("/tmp", "artifacts") - if not os.path.exists(artifact_cache): - os.makedirs(artifact_cache) + delete_repos_and_distros(pulpcore_bindings, ansible_bindings, monitor_task, reponames=reponames) - reponames = sorted(set([x["repository_name"] for x in specs])) + created_dists, created_repos = create_repos_and_dists( + ansible_bindings, + gen_object_with_cleanup, + monitor_task, + signing_body, + repo_specs, + specs, + ) - delete_repos_and_distros(ansible_bindings, reponames=reponames) + # keep track of what got uploaded + uploaded_artifacts = {} - created_dists, created_repos = create_repos_and_dists( - ansible_bindings, - gen_object_with_cleanup, - monitor_task, - signing_body, - repo_specs, - specs, - ) + # make and upload each cv + for ids, spec in enumerate(specs): + ckey = (spec["namespace"], spec["name"], spec["version"]) + + """ + if spec["repository_name"] in created_dists: + pulp_dist = created_dists[spec["repository_name"]] + else: + pulp_dist = {"base_path": spec["repository_name"]} + """ + + if ckey not in uploaded_artifacts: + # upload to the repo ... + build_spec = copy.deepcopy(spec) + build_spec["repository"] = "https://github.com/foo/bar" + cv_fn = ansible_collection_factory(config=build_spec).filename + specs[ids]["artifact"] = cv_fn + body = { + "file": cv_fn, + "repository": created_repos[spec["repository_name"]]["pulp_href"], + } + res = monitor_task(ansible_bindings.ContentCollectionVersionsApi.create(**body).task) + assert res.state == "completed" + uploaded_artifacts[ckey] = cv_fn - # keep track of what got uploaded - uploaded_artifacts = {} + else: + # copy to the repo ... + # https://docs.pulpproject.org/pulp_rpm/workflows/copy.html + repo = created_repos[spec["repository_name"]] + repo_href = repo["pulp_href"] + cvs = get_collection_versions(ansible_bindings) + this_cv = cvs[ckey] + cv_href = this_cv["pulp_href"] + payload = {"add_content_units": [cv_href]} + res = monitor_task( + ansible_bindings.RepositoriesAnsibleApi.modify(repo_href, payload).task + ) + assert res.state == "completed" - # make and upload each cv - for ids, spec in enumerate(specs): + # sign it ... + if spec.get("signed"): + cvs = get_collection_versions(ansible_bindings) ckey = (spec["namespace"], spec["name"], spec["version"]) + cv = cvs[ckey] + collection_url = cv["pulp_href"] + repo = created_repos[spec["repository_name"]] + body = { + "content_units": [collection_url], + "signing_service": ascii_armored_detached_signing_service.pulp_href, + } + res = monitor_task( + ansible_bindings.RepositoriesAnsibleApi.sign(repo["pulp_href"], body).task + ) + assert res.state == "completed" - """ - if spec["repository_name"] in created_dists: - pulp_dist = created_dists[spec["repository_name"]] - else: - pulp_dist = {"base_path": spec["repository_name"]} - """ - - if ckey not in uploaded_artifacts: - # upload to the repo ... - build_spec = copy.deepcopy(spec) - build_spec["repository"] = "https://github.com/foo/bar" - cv_fn = ansible_collection_factory(config=build_spec).filename - specs[ids]["artifact"] = cv_fn - body = { - "file": cv_fn, - "repository": created_repos[spec["repository_name"]]["pulp_href"], - } - res = monitor_task( - ansible_bindings.ContentCollectionVersionsApi.create(**body).task - ) - assert res.state == "completed" - uploaded_artifacts[ckey] = cv_fn - - else: - # copy to the repo ... - # https://docs.pulpproject.org/pulp_rpm/workflows/copy.html - repo = created_repos[spec["repository_name"]] - repo_href = repo["pulp_href"] - cvs = get_collection_versions(ansible_bindings) - this_cv = cvs[ckey] - cv_href = this_cv["pulp_href"] - payload = {"add_content_units": [cv_href]} - res = monitor_task( - ansible_bindings.RepositoriesAnsibleApi.modify(repo_href, payload).task - ) - assert res.state == "completed" - - # sign it ... - if spec.get("signed"): - cvs = get_collection_versions(ansible_bindings) - ckey = (spec["namespace"], spec["name"], spec["version"]) - cv = cvs[ckey] - collection_url = cv["pulp_href"] - repo = created_repos[spec["repository_name"]] - body = { - "content_units": [collection_url], - "signing_service": ascii_armored_detached_signing_service.pulp_href, - } - res = monitor_task( - ansible_bindings.RepositoriesAnsibleApi.sign(repo["pulp_href"], body).task - ) - assert res.state == "completed" - - # delete distributions so that some repos can hold CVs but not be "distributed" - current_dists = ansible_bindings.DistributionsAnsibleApi.list().results - current_dists = dict((x.name, x) for x in current_dists) - distros_deleted = [] - for spec in specs: - if not spec.get("has_distribution", True): - dname = spec["repository_name"] - if dname in distros_deleted: - continue - ansible_bindings.DistributionsAnsibleApi.delete(current_dists[dname].pulp_href) - distros_deleted.append(dname) - - # limit our actions to only the repos under test ... - reponames = sorted(set([x["repository_name"] for x in specs])) - - # remove stuff -after- it's copied around ... - for ids, spec in enumerate(specs): - if spec.get("removed") or spec.get("readded"): - cvs = get_collection_versions(ansible_bindings) - ckey = (spec["namespace"], spec["name"], spec["version"]) - cv = cvs[ckey] - collection_url = cv["pulp_href"] - repo = created_repos[spec["repository_name"]] - repo_href = repo["pulp_href"] - - payload = {"remove_content_units": [collection_url]} - res = monitor_task( - ansible_bindings.RepositoriesAnsibleApi.modify(repo_href, payload).task - ) - assert res.state == "completed" - - # re-add stuff - for ids, spec in enumerate(specs): - if spec.get("readded"): - cvs = get_collection_versions(ansible_bindings) - ckey = (spec["namespace"], spec["name"], spec["version"]) - cv = cvs[ckey] - collection_url = cv["pulp_href"] - repo = created_repos[spec["repository_name"]] - repo_href = repo["pulp_href"] - - payload = {"add_content_units": [collection_url]} - res = monitor_task( - ansible_bindings.RepositoriesAnsibleApi.modify(repo_href, payload).task - ) - assert res.state == "completed" + # delete distributions so that some repos can hold CVs but not be "distributed" + current_dists = ansible_bindings.DistributionsAnsibleApi.list().results + current_dists = dict((x.name, x) for x in current_dists) + distros_deleted = [] + for spec in specs: + if not spec.get("has_distribution", True): + dname = spec["repository_name"] + if dname in distros_deleted: + continue + ansible_bindings.DistributionsAnsibleApi.delete(current_dists[dname].pulp_href) + distros_deleted.append(dname) + + # limit our actions to only the repos under test ... + reponames = sorted(set([x["repository_name"] for x in specs])) - # generate some new repo version numbers to ensure content shows up - reponames = [x["repository_name"] for x in specs] - for reponame in reponames: + # remove stuff -after- it's copied around ... + for ids, spec in enumerate(specs): + if spec.get("removed") or spec.get("readded"): + cvs = get_collection_versions(ansible_bindings) + ckey = (spec["namespace"], spec["name"], spec["version"]) + cv = cvs[ckey] + collection_url = cv["pulp_href"] repo = created_repos[spec["repository_name"]] repo_href = repo["pulp_href"] - # what should be IN the repo already? - candidates = [x for x in specs if x.get("repository_name") == reponame] - candidates = [x for x in candidates if not x.get("removed") and not x.get("readded")] - if not candidates: - continue + payload = {"remove_content_units": [collection_url]} + res = monitor_task( + ansible_bindings.RepositoriesAnsibleApi.modify(repo_href, payload).task + ) + assert res.state == "completed" - # pick one at random - spec = random.choice(candidates) + # re-add stuff + for ids, spec in enumerate(specs): + if spec.get("readded"): + cvs = get_collection_versions(ansible_bindings) ckey = (spec["namespace"], spec["name"], spec["version"]) cv = cvs[ckey] collection_url = cv["pulp_href"] + repo = created_repos[spec["repository_name"]] + repo_href = repo["pulp_href"] - # add it to the repo to bump the repo version and - # validate the other CVs continue to live in "latest" payload = {"add_content_units": [collection_url]} res = monitor_task( ansible_bindings.RepositoriesAnsibleApi.modify(repo_href, payload).task ) assert res.state == "completed" - # make some deprecations ... - for ids, spec in enumerate(specs): - if spec.get("deprecated"): - result = monitor_task( - ansible_bindings.PulpAnsibleApiV3CollectionsApi.update( - spec["name"], - spec["namespace"], - spec["repository_name"], - {"deprecated": True}, - ).task - ) - assert result.state == "completed", result - - # make new specs with the enumerated content of all repos ... - reponames = sorted( - set([x["repository_name"] for x in specs if x.get("has_distribution", True)]) - ) - - # map out all of the known distributed CVs - new_specs = get_collection_versions_by_repo(ansible_bindings, repo_names=reponames) + # generate some new repo version numbers to ensure content shows up + reponames = [x["repository_name"] for x in specs] + for reponame in reponames: + repo = created_repos[spec["repository_name"]] + repo_href = repo["pulp_href"] + + # what should be IN the repo already? + candidates = [x for x in specs if x.get("repository_name") == reponame] + candidates = [x for x in candidates if not x.get("removed") and not x.get("readded")] + if not candidates: + continue + + # pick one at random + spec = random.choice(candidates) + ckey = (spec["namespace"], spec["name"], spec["version"]) + cv = cvs[ckey] + collection_url = cv["pulp_href"] + + # add it to the repo to bump the repo version and + # validate the other CVs continue to live in "latest" + payload = {"add_content_units": [collection_url]} + res = monitor_task(ansible_bindings.RepositoriesAnsibleApi.modify(repo_href, payload).task) + assert res.state == "completed" + + # make some deprecations ... + for ids, spec in enumerate(specs): + if spec.get("deprecated"): + result = monitor_task( + ansible_bindings.PulpAnsibleApiV3CollectionsApi.update( + spec["name"], + spec["namespace"], + spec["repository_name"], + {"deprecated": True}, + ).task + ) + assert result.state == "completed", result - with open(cachefile, "wb") as f: - pickle.dump(new_specs, f) + # make new specs with the enumerated content of all repos ... + reponames = sorted( + set([x["repository_name"] for x in specs if x.get("has_distribution", True)]) + ) - if new_specs is None: - with open(cachefile, "rb") as f: - new_specs = pickle.loads(f.read()) + # map out all of the known distributed CVs + new_specs = get_collection_versions_by_repo(ansible_bindings, repo_names=reponames) - yield new_specs + return new_specs class TestCrossRepoSearchFilters: """Validate the cross repo search endpoint filters.""" - cachefile = os.path.join("/tmp", "xrepo_cache.pickle") - clean = True - # clean = False - - @classmethod - def setup_class(cls): - """Make spec building a singleton.""" - if os.path.exists(cls.cachefile): - os.remove(cls.cachefile) - - @classmethod - def teardown_class(cls): - """Make spec building a singleton.""" - if os.path.exists(cls.cachefile): - os.remove(cls.cachefile) - def _run_search(self, search_client, specs, specs_filter, search_filters): if specs_filter: keep = [] @@ -916,42 +865,37 @@ def test_collection_version_search_by_not_signed(self, ansible_bindings, search_ def test_cross_repo_search_index_on_distribution_without_repository( - ansible_bindings, gen_object_with_cleanup + ansible_bindings, ansible_distribution_factory ): """Make sure no indexes are created for a repo-less distribution.""" - distro_data = gen_distribution() - distro = gen_object_with_cleanup(ansible_bindings.DistributionsAnsibleApi, distro_data) - dist_id = distro.pulp_href.split("/")[-2] + distribution = ansible_distribution_factory() + distribution_id = distribution.pulp_href.split("/")[-2] resp = ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( - limit=1000, distribution=[dist_id] + limit=1000, distribution=[distribution_id] ) assert resp.meta.count == 0 def test_cross_repo_search_index_on_distribution_with_repository_latest_version( ansible_bindings, + ansible_repository_factory, + ansible_distribution_factory, build_and_upload_collection, - gen_object_with_cleanup, ): """Make sure indexes are created for a distribution that points at a repo version.""" - pulp_repo = gen_object_with_cleanup( - ansible_bindings.RepositoriesAnsibleApi, {"name": str(uuid.uuid4())} - ) - build_and_upload_collection(ansible_repo=pulp_repo) + repository = ansible_repository_factory() + build_and_upload_collection(ansible_repo=repository) # get the latest repo version ... - repository_versions = ansible_bindings.RepositoriesAnsibleVersionsApi.list(pulp_repo.pulp_href) + repository_versions = ansible_bindings.RepositoriesAnsibleVersionsApi.list(repository.pulp_href) repository_version_latest = repository_versions.results[0] # make a distro that points only at the latest repo version ... - distro = gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name, - "base_path": pulp_repo.name, - "repository_version": repository_version_latest.pulp_href, - }, + distro = ansible_distribution_factory( + name=repository.name, + base_path=repository.name, + repository_version=repository_version_latest.pulp_href, ) # make sure the CV was indexed @@ -964,28 +908,24 @@ def test_cross_repo_search_index_on_distribution_with_repository_latest_version( def test_cross_repo_search_index_on_distribution_with_repository_previous_version( ansible_bindings, + ansible_repository_factory, + ansible_distribution_factory, build_and_upload_collection, - gen_object_with_cleanup, ): """Make sure indexes are created for a distribution that points at the latest repo version.""" - pulp_repo = gen_object_with_cleanup( - ansible_bindings.RepositoriesAnsibleApi, {"name": str(uuid.uuid4())} - ) - build_and_upload_collection(ansible_repo=pulp_repo) + repository = ansible_repository_factory() + build_and_upload_collection(ansible_repo=repository) # get the latest repo version ... - repository_versions = ansible_bindings.RepositoriesAnsibleVersionsApi.list(pulp_repo.pulp_href) + repository_versions = ansible_bindings.RepositoriesAnsibleVersionsApi.list(repository.pulp_href) repository_version_latest = repository_versions.results[0] # make a distro that points only at the latest repo version ... - distro = gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name, - "base_path": pulp_repo.name, - "repository_version": repository_version_latest.pulp_href, - }, + distro = ansible_distribution_factory( + name=repository.name, + base_path=repository.name, + repository_version=repository_version_latest.pulp_href, ) # make sure the CV was indexed @@ -1050,8 +990,9 @@ def test_cross_repo_search_index_on_repository_version_latest_filter( def test_cross_repo_search_index_on_multi_distro_single_repo( ansible_bindings, + ansible_repository_factory, + ansible_distribution_factory, build_and_upload_collection, - gen_object_with_cleanup, ): """Make sure indexes are created for a repo with multiple distributions.""" @@ -1062,9 +1003,7 @@ def test_cross_repo_search_index_on_multi_distro_single_repo( } # make the repo - pulp_repo = gen_object_with_cleanup( - ansible_bindings.RepositoriesAnsibleApi, {"name": str(uuid.uuid4())} - ) + pulp_repo = ansible_repository_factory() repo_id = pulp_repo.pulp_href.split("/")[-2] # add a collection to bump the version number @@ -1075,13 +1014,10 @@ def test_cross_repo_search_index_on_multi_distro_single_repo( repository_version_latest = repository_versions.results[0] # make a distro that points at the first version - gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name + "_v1", - "base_path": pulp_repo.name + "_v1", - "repository_version": repository_version_latest.pulp_href, - }, + ansible_distribution_factory( + name=pulp_repo.name + "_v1", + base_path=pulp_repo.name + "_v1", + repository_version=repository_version_latest.pulp_href, ) # we should now have 1 index @@ -1102,13 +1038,10 @@ def test_cross_repo_search_index_on_multi_distro_single_repo( repository_version_latest = repository_versions.results[0] # make a distro that points at the second version - gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name + "_v2", - "base_path": pulp_repo.name + "_v2", - "repository_version": repository_version_latest.pulp_href, - }, + ansible_distribution_factory( + name=pulp_repo.name + "_v2", + base_path=pulp_repo.name + "_v2", + repository_version=repository_version_latest.pulp_href, ) # per david, we should have 3 entries now @@ -1128,13 +1061,10 @@ def test_cross_repo_search_index_on_multi_distro_single_repo( build_and_upload_collection(ansible_repo=pulp_repo, config=build_config) # make a distro that points at the repository instead of a version - gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name + "_vN", - "base_path": pulp_repo.name + "_vN", - "repository": pulp_repo.pulp_href, - }, + ansible_distribution_factory( + name=pulp_repo.name + "_vN", + base_path=pulp_repo.name + "_vN", + repository=pulp_repo, ) # per david, we should have 6 entries now @@ -1252,23 +1182,18 @@ def test_cross_repo_search_index_on_distro_no_repo_version_and_removed_cv( def test_cross_repo_search_index_on_deleted_distro( ansible_bindings, + ansible_repository_factory, + ansible_distribution_factory, build_and_upload_collection, - gen_object_with_cleanup, monitor_task, ): """Make sure a deleted distro triggers an index cleanup.""" - pulp_repo = gen_object_with_cleanup( - ansible_bindings.RepositoriesAnsibleApi, {"name": str(uuid.uuid4())} - ) + pulp_repo = ansible_repository_factory() - # make a distro that points only at the repo ... - distro = gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name, - "base_path": pulp_repo.name, - "repository": pulp_repo.pulp_href, - }, + distro = ansible_distribution_factory( + name=pulp_repo.name, + base_path=pulp_repo.name, + repository=pulp_repo, ) # upload a CV @@ -1281,7 +1206,7 @@ def test_cross_repo_search_index_on_deleted_distro( assert resp.meta.count == 1 # now delete the distro ... - ansible_bindings.DistributionsAnsibleApi.delete(distro.pulp_href) + monitor_task(ansible_bindings.DistributionsAnsibleApi.delete(distro.pulp_href).task) # make sure the CV is not indexed resp = ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( @@ -1292,33 +1217,24 @@ def test_cross_repo_search_index_on_deleted_distro( def test_cross_repo_search_index_on_deleted_distro_with_another_still_remaining( ansible_bindings, + ansible_repository_factory, + ansible_distribution_factory, build_and_upload_collection, - gen_object_with_cleanup, monitor_task, ): """Make sure a deleted distro only triggers cleanup if no distros point at the repo.""" - pulp_repo = gen_object_with_cleanup( - ansible_bindings.RepositoriesAnsibleApi, {"name": str(uuid.uuid4())} - ) + pulp_repo = ansible_repository_factory() - # make a distro that points only at the repo ... - distro1 = gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name + "1", - "base_path": pulp_repo.name + "1", - "repository": pulp_repo.pulp_href, - }, + distro1 = ansible_distribution_factory( + name=pulp_repo.name + "1", + base_path=pulp_repo.name + "1", + repository=pulp_repo, ) - # make a distro that points only at the repo ... - gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name + "2", - "base_path": pulp_repo.name + "2", - "repository": pulp_repo.pulp_href, - }, + ansible_distribution_factory( + name=pulp_repo.name + "2", + base_path=pulp_repo.name + "2", + repository=pulp_repo, ) # upload a CV @@ -1331,7 +1247,7 @@ def test_cross_repo_search_index_on_deleted_distro_with_another_still_remaining( assert resp.meta.count == 1 # now delete the distro ... - ansible_bindings.DistributionsAnsibleApi.delete(distro1.pulp_href) + monitor_task(ansible_bindings.DistributionsAnsibleApi.delete(distro1.pulp_href).task) # make sure the CV is still indexed based on the existence of distro2 ... resp = ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( @@ -1389,29 +1305,20 @@ def test_cross_repo_search_index_on_distribution_with_repository_and_deprecation def test_cross_repo_search_index_with_updated_namespace_metadata( add_to_cleanup, ansible_bindings, + ansible_repository_factory, + ansible_distribution_factory, build_and_upload_collection, - gen_object_with_cleanup, monitor_task, random_image_factory, ): """Make sure namespace metdata updates are reflected in the index.""" - # make a repo - pulp_repo = gen_object_with_cleanup( - ansible_bindings.RepositoriesAnsibleApi, {"name": str(uuid.uuid4())} - ) + repository = ansible_repository_factory() + name = repository.name + distribution = ansible_distribution_factory(name=name, base_path=name, repository=repository) - # make a distro that points at the repository - distro = gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name, - "base_path": pulp_repo.name, - "repository": pulp_repo.pulp_href, - }, - ) - dist_id = distro.pulp_href.split("/")[-2] - distro_kwargs = {"path": distro.base_path, "distro_base_path": distro.base_path} + dist_id = distribution.pulp_href.split("/")[-2] + distribution_kwargs = {"path": name, "distro_base_path": name} # define col namespace namespace_name = randstr() @@ -1421,7 +1328,7 @@ def test_cross_repo_search_index_with_updated_namespace_metadata( # make namespace metadata task = ansible_bindings.PulpAnsibleApiV3PluginAnsibleContentNamespacesApi.create( - name=namespace_name, description="hello", company="Testing Co.", **distro_kwargs + name=namespace_name, description="hello", company="Testing Co.", **distribution_kwargs ) result = monitor_task(task.task) namespace_href = [x for x in result.created_resources if "namespaces" in x][0] @@ -1431,17 +1338,19 @@ def test_cross_repo_search_index_with_updated_namespace_metadata( # make and publish a collection build_and_upload_collection( - ansible_repo=pulp_repo, config={"namespace": namespace_name, "name": collection_name} + ansible_repo=repository, config={"namespace": namespace_name, "name": collection_name} ) # make sure the CV was indexed - resp = ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( - limit=1000, distribution=[dist_id] + response = ( + ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( + limit=1000, distribution=[dist_id] + ) ) - assert resp.meta.count == 1, resp + assert response.meta.count == 1, response # did it get all the metadata? - cv = resp.data[0] + cv = response.data[0] assert cv.namespace_metadata.pulp_href == namespace_href assert cv.namespace_metadata.avatar_url is None # assert cv.namespace_metadata.avatar_sha256 is None @@ -1456,7 +1365,7 @@ def test_cross_repo_search_index_with_updated_namespace_metadata( description="hello 2", company="Testing Co. redux", avatar=avatar_path, - **distro_kwargs, + **distribution_kwargs, ) result2 = monitor_task(task2.task) namespace2_href = [x for x in result2.created_resources if "namespaces" in x][0] @@ -1465,13 +1374,15 @@ def test_cross_repo_search_index_with_updated_namespace_metadata( ) # make sure the CV was re-indexed - resp2 = ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( - limit=1000, distribution=[dist_id] + response2 = ( + ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( + limit=1000, distribution=[dist_id] + ) ) - assert resp2.meta.count == 1, resp2 + assert response2.meta.count == 1, response2 # did it get all the NEW metadata? - cv2 = resp2.data[0] + cv2 = response2.data[0] assert cv2.namespace_metadata.pulp_href == namespace2_href assert cv2.namespace_metadata.avatar_url is not None # assert cv2.namespace_metadata.avatar_sha256 is not None @@ -1482,22 +1393,14 @@ def test_cross_repo_search_index_with_updated_namespace_metadata( def test_cross_repo_search_semantic_version_ordering( ansible_bindings, + ansible_repository_factory, + ansible_distribution_factory, build_and_upload_collection, - gen_object_with_cleanup, ): """Make sure collections are properly sorted using the order_by='version' parameter.""" - pulp_repo = gen_object_with_cleanup( - ansible_bindings.RepositoriesAnsibleApi, {"name": str(uuid.uuid4())} - ) - - gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name, - "base_path": pulp_repo.name, - "repository": pulp_repo.pulp_href, - }, - ) + repository = ansible_repository_factory() + name = repository.name + ansible_distribution_factory(name=name, base_path=name, repository=repository) versions = [ "2.0.0", @@ -1512,17 +1415,18 @@ def test_cross_repo_search_semantic_version_ordering( "1.0.1", "1.0.0", ] + # Make sure versions are correctly sorted according to Semantic Versioning. + assert versions == sorted(versions, key=Version, reverse=True) for version in versions: - build_and_upload_collection(ansible_repo=pulp_repo, config={"version": version}) + build_and_upload_collection(ansible_repo=repository, config={"version": version}) - resp = ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( - limit=1000, order_by=["-version"], repository_name=[pulp_repo.name] + response = ( + ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( + limit=1000, order_by=["-version"], repository_name=[name] + ) ) - built_collection_versions = [col.collection_version.version for col in resp.data] - - # Make sure versions are correctly sorted according to Semantic Versioning. - assert versions == sorted(versions, key=Version, reverse=True) + built_collection_versions = [col.collection_version.version for col in response.data] assert versions == built_collection_versions From 9f740beeb1a50227e9e453b3749e4db52100e7a3 Mon Sep 17 00:00:00 2001 From: Matthias Dellweg Date: Thu, 30 Jan 2025 13:10:37 +0100 Subject: [PATCH 2/3] Rewrite test_serializers --- .../v3/test_collection_version_search.py | 193 +++++++---------- .../api/collection/v3/test_serializers.py | 200 ++++++++---------- pulp_ansible/tests/functional/utils.py | 123 ----------- 3 files changed, 160 insertions(+), 356 deletions(-) diff --git a/pulp_ansible/tests/functional/api/collection/v3/test_collection_version_search.py b/pulp_ansible/tests/functional/api/collection/v3/test_collection_version_search.py index ccbec12dd..3666cc97f 100644 --- a/pulp_ansible/tests/functional/api/collection/v3/test_collection_version_search.py +++ b/pulp_ansible/tests/functional/api/collection/v3/test_collection_version_search.py @@ -1,17 +1,11 @@ import copy import os import random -import uuid from semantic_version import Version import pytest -from pulp_ansible.tests.functional.utils import ( - gen_distribution, - gen_remote, - gen_repo, - randstr, -) +from pulp_ansible.tests.functional.utils import randstr # We need to cary a copy of this fixture with extended scope for now. Regret... @@ -428,7 +422,8 @@ def delete_repos_and_distros(pulpcore_bindings, ansible_bindings, monitor_task, def create_repos_and_dists( ansible_bindings, - gen_object_with_cleanup, + ansible_repository_factory, + ansible_distribution_factory, monitor_task, signing_body, repo_specs, @@ -440,30 +435,19 @@ def create_repos_and_dists( # create repo & distro ... for ids, spec in enumerate(specs): # make the repo - if spec["repository_name"] not in created_repos: - repo_data = gen_repo(name=spec["repository_name"]) - if repo_specs.get(spec["repository_name"], {}).get("pulp_labels"): - repo_data["pulp_labels"] = repo_specs[spec["repository_name"]]["pulp_labels"] + if (name := spec["repository_name"]) not in created_repos: + repo_data = {"name": name} + if pulp_labels := repo_specs.get(name, {}).get("pulp_labels"): + repo_data["pulp_labels"] = pulp_labels - pulp_repo = gen_object_with_cleanup(ansible_bindings.RepositoriesAnsibleApi, repo_data) - created_repos[pulp_repo.name] = pulp_repo.to_dict() - - # sign the repo? - repository_href = pulp_repo.pulp_href - res = monitor_task( - ansible_bindings.RepositoriesAnsibleApi.sign(repository_href, signing_body).task - ) - assert res.state == "completed" + repository = ansible_repository_factory(**repo_data) + created_repos[name] = repository.to_dict() - # make the distribution - if spec["repository_name"] not in created_dists: - dist_data = gen_distribution( - name=pulp_repo.name, - base_path=pulp_repo.name, - repository=pulp_repo.pulp_href, + # make the distribution + distribution = ansible_distribution_factory( + name=name, base_path=name, repository=repository ) - dist = gen_object_with_cleanup(ansible_bindings.DistributionsAnsibleApi, dist_data) - created_dists[dist.name] = dist.to_dict() + created_dists[name] = distribution.to_dict() return created_dists, created_repos @@ -472,11 +456,12 @@ def create_repos_and_dists( def search_specs( pulpcore_bindings, ansible_bindings, + ansible_repository_factory, + ansible_distribution_factory, ansible_collection_factory, signing_gpg_homedir_path, ascii_armored_detached_signing_service, monitor_task, - gen_object_with_cleanup, ): repo_specs = REPO_SPECS specs = copy.deepcopy(SPECS) @@ -497,7 +482,8 @@ def search_specs( created_dists, created_repos = create_repos_and_dists( ansible_bindings, - gen_object_with_cleanup, + ansible_repository_factory, + ansible_distribution_factory, monitor_task, signing_body, repo_specs, @@ -938,18 +924,16 @@ def test_cross_repo_search_index_on_distribution_with_repository_previous_versio def test_cross_repo_search_index_on_repository_without_distribution( ansible_bindings, + ansible_repository_factory, build_and_upload_collection, - gen_object_with_cleanup, ): """Make sure no indexes are created for a repo without a distribution.""" - pulp_repo = gen_object_with_cleanup( - ansible_bindings.RepositoriesAnsibleApi, {"name": str(uuid.uuid4())} - ) - build_and_upload_collection(ansible_repo=pulp_repo) + repository = ansible_repository_factory() + build_and_upload_collection(ansible_repo=repository) # make sure nothing was indexed - repo_id = pulp_repo.pulp_href.split("/")[-2] + repo_id = repository.pulp_href.split("/")[-2] resp = ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( limit=1000, repository=[repo_id] ) @@ -958,32 +942,28 @@ def test_cross_repo_search_index_on_repository_without_distribution( def test_cross_repo_search_index_on_repository_version_latest_filter( ansible_bindings, + ansible_repository_factory, + ansible_distribution_factory, build_and_upload_collection, - gen_object_with_cleanup, ): """Make sure 'latest' is acceptable as a repo version filter string.""" - pulp_repo = gen_object_with_cleanup( - ansible_bindings.RepositoriesAnsibleApi, {"name": str(uuid.uuid4())} - ) - build_and_upload_collection(ansible_repo=pulp_repo) + repository = ansible_repository_factory() + build_and_upload_collection(ansible_repo=repository) # get the latest repo version ... - repository_versions = ansible_bindings.RepositoriesAnsibleVersionsApi.list(pulp_repo.pulp_href) + repository_versions = ansible_bindings.RepositoriesAnsibleVersionsApi.list(repository.pulp_href) repository_version_latest = repository_versions.results[0] # make a distro that points only at the latest repo version ... - gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name, - "base_path": pulp_repo.name, - "repository_version": repository_version_latest.pulp_href, - }, + ansible_distribution_factory( + name=repository.name, + base_path=repository.name, + repository_version=repository_version_latest.pulp_href, ) # make sure the CV was indexed resp = ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( - limit=1000, repository_name=[pulp_repo.name], repository_version="latest" + limit=1000, repository_name=[repository.name], repository_version="latest" ) assert resp.meta.count == 1 @@ -1083,99 +1063,80 @@ def test_cross_repo_search_index_on_multi_distro_single_repo( def test_cross_repo_search_index_with_double_sync( ansible_bindings, + ansible_collection_remote_factory, + ansible_sync_factory, + ansible_distribution_factory, build_and_upload_collection, - gen_object_with_cleanup, - monitor_task, ): """Make sure indexes are created properly for incremental syncs.""" - # make the repo - pulp_repo = gen_object_with_cleanup( - ansible_bindings.RepositoriesAnsibleApi, {"name": str(uuid.uuid4())} - ) - repo_id = pulp_repo.pulp_href.split("/")[-2] - - # make a distro that points at the repository instead of a version - gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name + "_vN", - "base_path": pulp_repo.name + "_vN", - "repository": pulp_repo.pulp_href, - }, - ) - # create the remote - remote_body = gen_remote( + remote = ansible_collection_remote_factory( url="https://galaxy.ansible.com", requirements_file="collections:\n - name: community.molecule\n version: 0.1.0", sync_dependencies=False, ) - # remote = ansible_bindings.RemotesCollectionApi.create(remote_body) - remote = gen_object_with_cleanup(ansible_bindings.RemotesCollectionApi, remote_body) - # sync against the remote - task = ansible_bindings.RepositoriesAnsibleApi.sync( - pulp_repo.pulp_href, {"remote": remote.pulp_href} + # sync into a repository + repository = ansible_sync_factory(remote=remote.pulp_href) + repository_id = repository.pulp_href.split("/")[-2] + + # make a distro that points at the repository instead of a version + ansible_distribution_factory( + name=repository.name + "_vN", + base_path=repository.name + "_vN", + repository=repository, ) - monitor_task(task.task) # reconfigure the remote with a different collection - col2 = "collections:\n - name: geerlingguy.mac\n version: 1.0.0" - remote_body_2 = copy.deepcopy(remote_body) - remote_body_2["requirements_file"] = col2 - ansible_bindings.RemotesCollectionApi.update(remote.pulp_href, remote_body_2) - - # sync again with new config - task = ansible_bindings.RepositoriesAnsibleApi.sync( - pulp_repo.pulp_href, {"remote": remote.pulp_href} + ansible_bindings.RemotesCollectionApi.partial_update( + remote.pulp_href, + {"requirements_file": "collections:\n - name: geerlingguy.mac\n version: 1.0.0"}, ) - monitor_task(task.task) + # sync again with new config + repository = ansible_sync_factory(ansible_repo=repository, remote=remote.pulp_href) resp = ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( - limit=1000, repository=[repo_id] + limit=1000, repository=[repository_id] ) assert resp.meta.count == 2 def test_cross_repo_search_index_on_distro_no_repo_version_and_removed_cv( ansible_bindings, + ansible_repository_factory, + ansible_distribution_factory, build_and_upload_collection, - gen_object_with_cleanup, monitor_task, ): """Make sure a removed CV doesn't show up.""" - pulp_repo = gen_object_with_cleanup( - ansible_bindings.RepositoriesAnsibleApi, {"name": str(uuid.uuid4())} - ) + repository = ansible_repository_factory() # make a distro that points only at the repo ... - gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name, - "base_path": pulp_repo.name, - "repository": pulp_repo.pulp_href, - }, + ansible_distribution_factory( + name=repository.name, + base_path=repository.name, + repository=repository, ) - cv = build_and_upload_collection(ansible_repo=pulp_repo) + cv = build_and_upload_collection(ansible_repo=repository) + # make sure the CV was indexed resp = ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( - limit=1000, repository_name=[pulp_repo.name], repository_version="latest" + limit=1000, repository_name=[repository.name], repository_version="latest" ) assert resp.meta.count == 1 # now remove the CV from the repo payload = {"remove_content_units": [cv[1]]} res = monitor_task( - ansible_bindings.RepositoriesAnsibleApi.modify(pulp_repo.pulp_href, payload).task + ansible_bindings.RepositoriesAnsibleApi.modify(repository.pulp_href, payload).task ) assert res.state == "completed" # make sure the CV is not indexed resp = ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( - limit=1000, repository_name=[pulp_repo.name], repository_version="latest" + limit=1000, repository_name=[repository.name], repository_version="latest" ) assert resp.meta.count == 0 @@ -1258,43 +1219,37 @@ def test_cross_repo_search_index_on_deleted_distro_with_another_still_remaining( def test_cross_repo_search_index_on_distribution_with_repository_and_deprecation( ansible_bindings, + ansible_repository_factory, + ansible_distribution_factory, build_and_upload_collection, - gen_object_with_cleanup, monitor_task, ): """Make sure indexes are marking deprecations.""" - pulp_repo = gen_object_with_cleanup( - ansible_bindings.RepositoriesAnsibleApi, {"name": str(uuid.uuid4())} - ) - col = build_and_upload_collection(ansible_repo=pulp_repo) + repository = ansible_repository_factory() + collection = build_and_upload_collection(ansible_repo=repository) - # make a distro that points only at the latest repo version ... - distro = gen_object_with_cleanup( - ansible_bindings.DistributionsAnsibleApi, - { - "name": pulp_repo.name, - "base_path": pulp_repo.name, - "repository": pulp_repo.pulp_href, - }, + # make a distribution that points only at the latest repo version ... + distribution = ansible_distribution_factory( + name=repository.name, base_path=repository.name, repository=repository ) # make a deprecation - namespace = col[0].namespace - name = col[0].name + namespace = collection[0].namespace + name = collection[0].name monitor_task( ansible_bindings.PulpAnsibleApiV3CollectionsApi.update( name, namespace, - pulp_repo.name, + repository.name, {"deprecated": True}, ).task ) # make sure the CV was indexed - dist_id = distro.pulp_href.split("/")[-2] + distribution_id = distribution.pulp_href.split("/")[-2] resp = ansible_bindings.PulpAnsibleDefaultApiV3PluginAnsibleSearchCollectionVersionsApi.list( - limit=1000, distribution=[dist_id] + limit=1000, distribution=[distribution_id] ) assert resp.meta.count == 1, resp diff --git a/pulp_ansible/tests/functional/api/collection/v3/test_serializers.py b/pulp_ansible/tests/functional/api/collection/v3/test_serializers.py index 944fe72b3..ed1c81ef8 100644 --- a/pulp_ansible/tests/functional/api/collection/v3/test_serializers.py +++ b/pulp_ansible/tests/functional/api/collection/v3/test_serializers.py @@ -1,116 +1,88 @@ """Tests related to Galaxy V3 serializers.""" -from pulpcore.client.pulp_ansible import ( - AnsibleRepositorySyncURL, - ContentCollectionVersionsApi, - DistributionsAnsibleApi, - PulpAnsibleApiV3CollectionsApi, - PulpAnsibleApiV3CollectionsVersionsApi, - RepositoriesAnsibleApi, - RemotesCollectionApi, -) -from pulp_smash.pulp3.bindings import monitor_task - -from pulp_ansible.tests.functional.utils import TestCaseUsingBindings -from pulp_ansible.tests.functional.utils import gen_ansible_client, gen_ansible_remote -from pulp_ansible.tests.functional.utils import tasks - - -class CollectionsV3TestCase(TestCaseUsingBindings): - """Test Collections V3 endpoint.""" - - @classmethod - def setUpClass(cls): - """Create class-wide variables.""" - cls.client = gen_ansible_client() - cls.repo_api = RepositoriesAnsibleApi(cls.client) - cls.remote_collection_api = RemotesCollectionApi(cls.client) - cls.distributions_api = DistributionsAnsibleApi(cls.client) - cls.collections_api = PulpAnsibleApiV3CollectionsApi(cls.client) - cls.collections_versions_api = ContentCollectionVersionsApi(cls.client) - cls.collections_versions_v3api = PulpAnsibleApiV3CollectionsVersionsApi(cls.client) - - def test_v3_updated_at(self): - """Test Collections V3 endpoint field: ``updated_at``.""" - - requirements1 = """ - collections: - - name: "pulp.squeezer" - version: "0.0.7" - """ - - requirements2 = """ - collections: - - name: "pulp.squeezer" - version: "0.0.17" - """ - - # sync the first version ... - body = gen_ansible_remote( - url="https://galaxy.ansible.com", - requirements_file=requirements1, - sync_dependencies=False, - ) - remote = self.remote_collection_api.create(body) - self.addCleanup(self.remote_collection_api.delete, remote.pulp_href) - - repo = self._create_repo_and_sync_with_remote(remote) - distribution = self._create_distribution_from_repo(repo) - - collections = self.collections_api.list(distribution.base_path) - - original_highest_version = collections.data[0].highest_version["version"] - original_updated_at = collections.data[0].updated_at - - original_total_versions = self.collections_versions_v3api.list( - "squeezer", "pulp", distribution.base_path - ).meta.count - - # sync the second version ... - body = gen_ansible_remote( - url="https://galaxy.ansible.com", - requirements_file=requirements2, - sync_dependencies=False, - ) - self.remote_collection_api.update(remote.pulp_href, body) - repository_sync_data = AnsibleRepositorySyncURL(remote=remote.pulp_href, optimize=True) - sync_response = self.repo_api.sync(repo.pulp_href, repository_sync_data) - monitor_task(sync_response.task) - task = tasks.read(sync_response.task) - assert task.state == "completed" - - # enumerate new data after 2nd sync ... - collections = self.collections_api.list(distribution.base_path) - highest_version = collections.data[0].highest_version["version"] - updated_at = collections.data[0].updated_at - total_versions = self.collections_versions_v3api.list( - "squeezer", "pulp", distribution.base_path - ).meta.count - - assert original_highest_version == "0.0.7" - assert highest_version == "0.0.17" - assert original_total_versions == 1 - assert total_versions == 2 - assert updated_at > original_updated_at - - def test_v3_collection_version_from_synced_data(self): - """Test Collection Versions V3 endpoint fields.""" - body = gen_ansible_remote( - url="https://galaxy.ansible.com", - requirements_file="collections:\n - name: cisco.nxos\n version: 1.4.0", - sync_dependencies=False, - ) - - remote = self.remote_collection_api.create(body) - self.addCleanup(self.remote_collection_api.delete, remote.pulp_href) - - repo = self._create_repo_and_sync_with_remote(remote) - distribution = self._create_distribution_from_repo(repo) - - version = self.collections_versions_v3api.read( - "nxos", "cisco", distribution.base_path, "1.4.0" - ) - - assert version.requires_ansible == ">=2.9.10,<2.11" - assert "'name': 'README.md'" in str(version.files) - assert version.manifest["collection_info"]["name"] == "nxos" + +def test_v3_updated_at( + ansible_bindings, + ansible_sync_factory, + ansible_collection_remote_factory, + ansible_distribution_factory, +): + """Test Collections V3 endpoint field: ``updated_at``.""" + + requirements1 = """ + collections: + - name: "pulp.squeezer" + version: "0.0.7" + """ + + requirements2 = """ + collections: + - name: "pulp.squeezer" + version: "0.0.17" + """ + + # sync the first version ... + remote = ansible_collection_remote_factory( + url="https://galaxy.ansible.com", + requirements_file=requirements1, + sync_dependencies=False, + ) + + repository = ansible_sync_factory(remote=remote.pulp_href) + distribution = ansible_distribution_factory(repository=repository) + + collections = ansible_bindings.PulpAnsibleApiV3CollectionsApi.list(distribution.base_path) + + original_highest_version = collections.data[0].highest_version["version"] + original_updated_at = collections.data[0].updated_at + + original_total_versions = ansible_bindings.PulpAnsibleApiV3CollectionsVersionsApi.list( + "squeezer", "pulp", distribution.base_path + ).meta.count + + # sync the second version ... + # Don't wait on the update task here. The sync will wait for us. + ansible_bindings.RemotesCollectionApi.partial_update( + remote.pulp_href, {"requirements_file": requirements2} + ) + + ansible_sync_factory(ansible_repo=repository, remote=remote.pulp_href, optimize=True) + + # enumerate new data after 2nd sync ... + collections = ansible_bindings.PulpAnsibleApiV3CollectionsApi.list(distribution.base_path) + highest_version = collections.data[0].highest_version["version"] + updated_at = collections.data[0].updated_at + total_versions = ansible_bindings.PulpAnsibleApiV3CollectionsVersionsApi.list( + "squeezer", "pulp", distribution.base_path + ).meta.count + + assert original_highest_version == "0.0.7" + assert highest_version == "0.0.17" + assert original_total_versions == 1 + assert total_versions == 2 + assert updated_at > original_updated_at + + +def test_v3_collection_version_from_synced_data( + ansible_bindings, + ansible_sync_factory, + ansible_collection_remote_factory, + ansible_distribution_factory, +): + """Test Collection Versions V3 endpoint fields.""" + remote = ansible_collection_remote_factory( + url="https://galaxy.ansible.com", + requirements_file="collections:\n - name: cisco.nxos\n version: 1.4.0", + sync_dependencies=False, + ) + + repository = ansible_sync_factory(remote=remote.pulp_href) + distribution = ansible_distribution_factory(repository=repository) + + version = ansible_bindings.PulpAnsibleApiV3CollectionsVersionsApi.read( + "nxos", "cisco", distribution.base_path, "1.4.0" + ) + + assert version.requires_ansible == ">=2.9.10,<2.11" + assert "'name': 'README.md'" in str(version.files) + assert version.manifest["collection_info"]["name"] == "nxos" diff --git a/pulp_ansible/tests/functional/utils.py b/pulp_ansible/tests/functional/utils.py index 753c33d2e..2bf7ed5ca 100644 --- a/pulp_ansible/tests/functional/utils.py +++ b/pulp_ansible/tests/functional/utils.py @@ -5,38 +5,16 @@ from urllib.parse import urlparse, parse_qs from pulp_smash import config -from pulp_smash.pulp3.bindings import delete_orphans, monitor_task, PulpTestCase from pulp_smash.pulp3.utils import ( - gen_distribution, gen_remote, - gen_repo, ) from pulp_ansible.tests.functional.constants import ( ANSIBLE_FIXTURE_URL, ) -from pulpcore.client.pulpcore import ( - ApiClient as CoreApiClient, - TasksApi, -) -from pulpcore.client.pulp_ansible import ( - ApiClient as AnsibleApiClient, - ContentCollectionVersionsApi, - DistributionsAnsibleApi, - PulpAnsibleApiV3CollectionsApi, - PulpAnsibleApiV3CollectionsVersionsApi, - RepositoriesAnsibleApi, - RemotesCollectionApi, - RemotesGitApi, - RemotesRoleApi, - AnsibleRepositorySyncURL, - RepositoriesAnsibleVersionsApi, -) - cfg = config.get_config() -configuration = cfg.get_bindings_config() def randstr(): @@ -48,11 +26,6 @@ def content_counts(repository_version, summary_type="present"): return {key: value["count"] for key, value in content_summary.items()} -def gen_ansible_client(): - """Return an OBJECT for ansible client.""" - return AnsibleApiClient(configuration) - - def gen_ansible_remote(url=ANSIBLE_FIXTURE_URL, include_pulp_auth=False, **kwargs): """Return a semi-random dict for use in creating a ansible Remote. @@ -68,102 +41,6 @@ def gen_ansible_remote(url=ANSIBLE_FIXTURE_URL, include_pulp_auth=False, **kwarg return gen_remote(url, **kwargs) -core_client = CoreApiClient(configuration) -tasks = TasksApi(core_client) - - -class TestCaseUsingBindings(PulpTestCase): - """A parent TestCase that instantiates the various bindings used throughout tests.""" - - @classmethod - def setUpClass(cls): - """Create class-wide variables.""" - cls.client = gen_ansible_client() - cls.repo_api = RepositoriesAnsibleApi(cls.client) - cls.repo_version_api = RepositoriesAnsibleVersionsApi(cls.client) - cls.remote_collection_api = RemotesCollectionApi(cls.client) - cls.remote_git_api = RemotesGitApi(cls.client) - cls.remote_role_api = RemotesRoleApi(cls.client) - cls.distributions_api = DistributionsAnsibleApi(cls.client) - cls.cv_api = ContentCollectionVersionsApi(cls.client) - cls.collections_v3api = PulpAnsibleApiV3CollectionsApi(cls.client) - cls.collections_versions_v3api = PulpAnsibleApiV3CollectionsVersionsApi(cls.client) - - @classmethod - def tearDownClass(cls): - """Clean class-wide variable.""" - delete_orphans() - - def _create_repo_and_sync_with_remote(self, remote, distribution=False, **repo_kwargs): - """ - Create a repository and then sync with the provided `remote`. - - Args: - remote: The remote to be sync with - - Returns: - repository: The created repository object to be asserted to. - """ - # Create the repository. - repo = self.repo_api.create(gen_repo(**repo_kwargs)) - self.addCleanup(self.repo_api.delete, repo.pulp_href) - if distribution: - self._create_distribution_from_repo(repo) - return self._sync_repo(repo, remote=remote.pulp_href) - - def _create_repo_with_attached_remote_and_sync(self, remote, **repo_kwargs): - """ - Create a repository with the remote attached, and then sync without specifying the `remote`. - - Args: - remote: The remote to attach to the repository - - Returns: - repository: The created repository object to be asserted to. - """ - # Create the repository. - repo = self.repo_api.create(gen_repo(remote=remote.pulp_href, **repo_kwargs)) - self.addCleanup(self.repo_api.delete, repo.pulp_href) - return self._sync_repo(repo) - - def _sync_repo(self, repo, **kwargs): - """ - Sync the repo with optional `kwarg` parameters passed on to the sync method. - - Args: - repo: The repository to sync - - Returns: - repository: The updated repository after the sync is complete - """ - repository_sync_data = AnsibleRepositorySyncURL(**kwargs) - sync_response = self.repo_api.sync(repo.pulp_href, repository_sync_data) - monitor_task(sync_response.task) - repo = self.repo_api.read(repo.pulp_href) - return repo - - def _create_distribution_from_repo(self, repo, cleanup=True): - """ - Create an `AnsibleDistribution` serving the `repo` with the `base_path`. - - Args: - repo: The repository to serve with the `AnsibleDistribution` - cleanup: Whether the distribution should be cleaned up - - Returns: - The created `AnsibleDistribution`. - """ - # Create a distribution. - body = gen_distribution() - body["repository"] = repo.pulp_href - distribution_create = self.distributions_api.create(body) - created_resources = monitor_task(distribution_create.task).created_resources - distribution = self.distributions_api.read(created_resources[0]) - if cleanup: - self.addCleanup(self.distributions_api.delete, distribution.pulp_href) - return distribution - - def iterate_all(list_func, **kwargs): """ Iterate through all of the items on every page in a paginated list view. From 7710b5c30f81ffe07a380053664288f209f8f349 Mon Sep 17 00:00:00 2001 From: Matthias Dellweg Date: Thu, 30 Jan 2025 16:18:12 +0100 Subject: [PATCH 3/3] Remove pulp-smash from functional test suite fixes #2083 --- CHANGES/2083.misc | 1 + functest_requirements.txt | 3 --- .../tests/functional/api/test_rbac.py | 19 +++++++------ pulp_ansible/tests/functional/utils.py | 27 ------------------- 4 files changed, 12 insertions(+), 38 deletions(-) create mode 100644 CHANGES/2083.misc diff --git a/CHANGES/2083.misc b/CHANGES/2083.misc new file mode 100644 index 000000000..b938fabd6 --- /dev/null +++ b/CHANGES/2083.misc @@ -0,0 +1 @@ +Rewrote functional test suite without pulp-smash. diff --git a/functest_requirements.txt b/functest_requirements.txt index 73e70ba5e..630b79d16 100644 --- a/functest_requirements.txt +++ b/functest_requirements.txt @@ -7,6 +7,3 @@ requests proxy.py~=2.4.9 trustme~=1.2.0 pytest-timeout - -# Legacy: -pulp-smash @ git+https://github.com/pulp/pulp-smash.git diff --git a/pulp_ansible/tests/functional/api/test_rbac.py b/pulp_ansible/tests/functional/api/test_rbac.py index f71acb6a9..89a5737d4 100644 --- a/pulp_ansible/tests/functional/api/test_rbac.py +++ b/pulp_ansible/tests/functional/api/test_rbac.py @@ -1,11 +1,10 @@ import pytest import uuid -from pulp_ansible.tests.functional.constants import ANSIBLE_GALAXY_URL -from pulp_ansible.tests.functional.utils import gen_ansible_remote - from pulpcore.client.pulp_ansible import ApiException, AsyncOperationResponse +from pulp_ansible.tests.functional.constants import ANSIBLE_GALAXY_URL + # TODO Find a way to make the factories work with try_action def gen_repo(): @@ -16,6 +15,10 @@ def gen_distribution(): return {"name": str(uuid.uuid4()), "base_path": str(uuid.uuid4())} +def gen_remote(): + return {"name": str(uuid.uuid4()), "url": ANSIBLE_GALAXY_URL, "rate_limit": 5} + + @pytest.fixture() def gen_users(gen_user): """Returns a user generator function for the tests.""" @@ -501,21 +504,21 @@ def test_remotes_rbac( remote_api, "create", 201, - gen_ansible_remote(url=ANSIBLE_GALAXY_URL), + gen_remote(), ) try_action( user_reader, remote_api, "create", 403, - gen_ansible_remote(url=ANSIBLE_GALAXY_URL), + gen_remote(), ) try_action( user_helpless, remote_api, "create", 403, - gen_ansible_remote(url=ANSIBLE_GALAXY_URL), + gen_remote(), ) # View testing @@ -524,7 +527,7 @@ def test_remotes_rbac( try_action(user_helpless, remote_api, "read", 404, remote.pulp_href) # Update testing - update_args = [remote.pulp_href, gen_ansible_remote(url=ANSIBLE_GALAXY_URL)] + update_args = [remote.pulp_href, gen_remote()] try_action(user_creator, remote_api, "update", 202, *update_args) try_action(user_reader, remote_api, "update", 403, *update_args) try_action(user_helpless, remote_api, "update", 404, *update_args) @@ -564,7 +567,7 @@ def test_remotes_role_management( remote_api, "create", 201, - gen_ansible_remote(url=ANSIBLE_GALAXY_URL), + gen_remote(), ) href = remote.pulp_href diff --git a/pulp_ansible/tests/functional/utils.py b/pulp_ansible/tests/functional/utils.py index 2bf7ed5ca..446d7f132 100644 --- a/pulp_ansible/tests/functional/utils.py +++ b/pulp_ansible/tests/functional/utils.py @@ -4,18 +4,6 @@ import string from urllib.parse import urlparse, parse_qs -from pulp_smash import config -from pulp_smash.pulp3.utils import ( - gen_remote, -) - -from pulp_ansible.tests.functional.constants import ( - ANSIBLE_FIXTURE_URL, -) - - -cfg = config.get_config() - def randstr(): return "".join(random.choices(string.ascii_lowercase, k=8)) @@ -26,21 +14,6 @@ def content_counts(repository_version, summary_type="present"): return {key: value["count"] for key, value in content_summary.items()} -def gen_ansible_remote(url=ANSIBLE_FIXTURE_URL, include_pulp_auth=False, **kwargs): - """Return a semi-random dict for use in creating a ansible Remote. - - :param url: The URL of an external content source. - """ - if include_pulp_auth: - kwargs["username"] = cfg.pulp_auth[0] - kwargs["password"] = cfg.pulp_auth[1] - - if "rate_limit" not in kwargs: - kwargs["rate_limit"] = 5 - - return gen_remote(url, **kwargs) - - def iterate_all(list_func, **kwargs): """ Iterate through all of the items on every page in a paginated list view.