def test_search_content_by_unit_type(populated_repo): """search_content on unit_type returns only units of that type""" crit = Criteria.with_unit_type(ModulemdUnit) units = list(populated_repo.search_content(crit)) assert sorted(units) == [ ModulemdUnit( unit_id="23a7711a-8133-2876-37eb-dcd9e87a1613", name="module1", stream="s1", version=1234, context="a1b2", arch="x86_64", repository_memberships=["repo1"], ), ModulemdUnit( unit_id="e6f4590b-9a16-4106-cf6a-659eb4862b21", name="module2", stream="s2", version=1234, context="a1b2", arch="x86_64", repository_memberships=["repo1"], ), ]
def clean_all_rpm_content(self): # Clear out old all-rpm-content LOG.info("Start old all-rpm-content deletion") arc_threshold = self.args.arc_threshold criteria = Criteria.and_( Criteria.with_unit_type(RpmUnit), Criteria.with_field( "cdn_published", Matcher.less_than(datetime.utcnow() - timedelta(days=arc_threshold)), ), ) clean_repos = list( self.pulp_client.search_repository( Criteria.with_field("id", "all-rpm-content"))) if not clean_repos: LOG.info("No repos found for cleaning.") return arc_repo = clean_repos[0] deleted_arc = list(arc_repo.remove_content(criteria=criteria)) deleted_content = [] for task in deleted_arc: if task.repo_id == "all-rpm-content": for unit in task.units: LOG.info("Old all-rpm-content deleted: %s", unit.name) deleted_content.append(unit) if not deleted_content: LOG.info("No all-rpm-content found older than %s", arc_threshold)
def get_advisories(self, advisory_ids): criteria = criteria = Criteria.and_( Criteria.with_unit_type(ErratumUnit), Criteria.with_id(advisory_ids) ) adv_f = self.search_content(criteria) advisories = [a for a in adv_f.result()] if not advisories: self.fail("Advisory(ies) not found: %s", ", ".join(sorted(advisory_ids))) return advisories
def test_copy_with_criteria(fast_poller, requests_mocker, client): """Copy with criteria succeeds, and serializes criteria correctly.""" src = Repository(id="src-repo") dest = Repository(id="dest-repo") src.__dict__["_client"] = client dest.__dict__["_client"] = client requests_mocker.post( "https://pulp.example.com/pulp/api/v2/repositories/dest-repo/actions/associate/", [{"json": {"spawned_tasks": [{"task_id": "task1"}, {"task_id": "task2"}]}}], ) requests_mocker.post( "https://pulp.example.com/pulp/api/v2/tasks/search/", [ { "json": [ {"task_id": "task1", "state": "finished"}, {"task_id": "task2", "state": "skipped"}, ] } ], ) crit = Criteria.and_( Criteria.with_unit_type(RpmUnit), Criteria.with_field("name", Matcher.in_(["bash", "glibc"])), ) # Copy should succeed, and return the tasks (in this case with no matches) assert sorted(client.copy_content(src, dest, crit), key=lambda t: t.id) == [ Task(id="task1", completed=True, succeeded=True), Task(id="task2", completed=True, succeeded=True), ] hist = requests_mocker.request_history # First request should have been the associate. assert ( hist[0].url == "https://pulp.example.com/pulp/api/v2/repositories/dest-repo/actions/associate/" ) # It should have encoded our criteria object as needed by the Pulp API. assert hist[0].json() == { "criteria": { "filters": {"unit": {"name": {"$in": ["bash", "glibc"]}}}, "type_ids": ["rpm", "srpm"], }, "source_repo_id": "src-repo", }
def test_stringify_complex_criteria(): crit = Criteria.and_( Criteria.with_field("must-exist", Matcher.exists()), Criteria.with_field("foo", Matcher.equals("bar")), Criteria.true(), Criteria.or_( Criteria.with_field("foo", Matcher.regex("quux")), Criteria.with_field("other", Matcher.in_(["x", "y", "z"])), Criteria.with_field("num", Matcher.less_than(9000)), ), Criteria.with_unit_type(FileUnit), ) assert (str(crit) == "((must-exist EXISTS) AND foo=='bar' AND TRUE " "AND (foo=~/quux/ OR (other IN ['x', 'y', 'z']) OR num<9000) " "AND (content_type_id IN ['iso']))")
def test_can_search_content_specific_fields(client, requests_mocker): """search_content can search while requesting specific fields.""" requests_mocker.get( "https://pulp.example.com/pulp/api/v2/plugins/types/", json=[{ "id": "iso" }], ) requests_mocker.post( "https://pulp.example.com/pulp/api/v2/content/units/iso/search/", json=[], ) client.search_content( Criteria.with_unit_type( FileUnit, unit_fields=[ "size", "sha256sum", "description", "version", "notexist" ], )).result() # Check the criteria it passed to the server... req = requests_mocker.request_history[-1] assert req.json() == { "criteria": { # Note the following behaviors: # - for an unknown field (notexist) we keep it with no changes # - for a mandatory field (name) we include it despite not being requested # - for fields with different model and pulp names (checksum) we use the # pulp name here # - for fields stored under an object (description, version) we use the # name of the outermost object (pulp_user_metadata) without duplicates. # "fields": ["checksum", "name", "notexist", "pulp_user_metadata", "size"], "filters": {}, "limit": 2000, "skip": 0, }, "include_repos": True, }
def test_search_fields(client, requests_mocker): """Searching with limited fields works correctly""" repo = Repository(id="some-repo") repo.__dict__["_client"] = client requests_mocker.post( "https://pulp.example.com/pulp/api/v2/repositories/some-repo/search/units/", json=[], ) crit = Criteria.and_( Criteria.with_unit_type(FileUnit, unit_fields=["sha256sum"]), Criteria.with_field("name", "hello.txt"), ) repo.search_content(crit).result() history = requests_mocker.request_history # There should have been just one request assert len(history) == 1 request = history[0] body = request.json() # This should have been the request body. assert body == { "criteria": { "type_ids": ["iso"], "skip": 0, "limit": 2000, "filters": { "unit": { "name": { "$eq": "hello.txt" } } }, "fields": { "unit": ["checksum", "name", "size"] }, } }
def test_remove_with_criteria(fast_poller, requests_mocker, client): """Remove succeeds when given a critria/filter for removal""" repo = Repository(id="some-repo") repo.__dict__["_client"] = client requests_mocker.post( "https://pulp.example.com/pulp/api/v2/repositories/some-repo/actions/unassociate/", [ { "json": { "spawned_tasks": [{ "task_id": "task1" }] } }, { "json": { "spawned_tasks": [{ "task_id": "task2" }] } }, ], ) requests_mocker.post( "https://pulp.example.com/pulp/api/v2/tasks/search/", [ { "json": [{ "task_id": "task1", "state": "finished" }] }, { "json": [{ "task_id": "task2", "state": "finished" }] }, ], ) criteria = Criteria.and_( Criteria.with_unit_type(RpmUnit), Criteria.with_field("filename", "some.rpm"), Criteria.with_field("signing_key", Matcher.in_(["key123"])), ) assert repo.remove_content(criteria=criteria).result() == [ Task(id="task1", completed=True, succeeded=True) ] # It should have passed the criteria to Pulp req = requests_mocker.request_history assert ( req[0].url == "https://pulp.example.com/pulp/api/v2/repositories/some-repo/actions/unassociate/" ) assert req[0].json() == { "criteria": { "filters": { "unit": { "$and": [ { "filename": { "$eq": "some.rpm" } }, { "signing_key": { "$in": ["key123"] } }, ] } }, "type_ids": ["rpm", "srpm"], } } # Providing both criteria and type_ids assert repo.remove_content(criteria=criteria, type_ids=["type1", "type2"]).result() == [ Task(id="task2", completed=True, succeeded=True) ] # It should have passed only the critera to Pulp and ignore type_ids as kwarg req = requests_mocker.request_history assert ( req[0].url == "https://pulp.example.com/pulp/api/v2/repositories/some-repo/actions/unassociate/" ) assert req[0].json() == { "criteria": { "filters": { "unit": { "$and": [ { "filename": { "$eq": "some.rpm" } }, { "signing_key": { "$in": ["key123"] } }, ] } }, "type_ids": ["rpm", "srpm"], } }
def unit_criteria(self, unit_type, partial_crit): criteria = Criteria.and_( Criteria.with_unit_type(unit_type), Criteria.or_(*partial_crit) ) return criteria
def get_erratum_from_pulp(self, advisory_id): crit = Criteria.and_(Criteria.with_unit_type(ErratumUnit), Criteria.with_id(advisory_id)) return self.pulp_client.search_content(criteria=crit).result()
def test_can_search_content_by_type(client, requests_mocker): """search_content can search for a specified unit type.""" requests_mocker.get( "https://pulp.example.com/pulp/api/v2/plugins/types/", json=[{ "id": "rpm" }, { "id": "srpm" }, { "id": "iso" }], ) # Note although "iso" is supported, we don't mock the search URL for # that content type, thus proving that we don't query it if we search # for a specific unit_type requests_mocker.post( "https://pulp.example.com/pulp/api/v2/content/units/rpm/search/", json=RPM_TEST_UNITS, ) requests_mocker.post( "https://pulp.example.com/pulp/api/v2/content/units/srpm/search/", json=SRPM_TEST_UNITS, ) units = client.search_content(Criteria.with_unit_type(RpmUnit)) # It should have returned the expected units assert sorted(units) == [ RpmUnit( unit_id="bd2e0321-48f6-4997-a5dc-e73c771bc17d", content_type_id="srpm", sha256sum= "4f5a3a0da6f404f6d9988987cd75f13982bd655a0a4f692406611afbbc597679", arch="src", epoch="0", name="glibc", release="2.57.el4.1", repository_memberships=["fake-repository-id-3"], sourcerpm=None, version="2.3.4", ), RpmUnit( unit_id="bd2e0321-48f6-4997-a5dc-e73c771bc17d", sha256sum= "4f5a3a0da6f404f6d9988987cd75f13982bd655a0a4f692406611afbbc597679", arch="ia64", epoch="0", name="glibc-headers", release="2.57.el4.1", repository_memberships=["fake-repository-id-3"], sourcerpm="glibc-2.3.4-2.57.el4.1.src.rpm", version="2.3.4", ), RpmUnit( unit_id="d4633746-1ccc-4d85-9733-0007c87e0724", sha1sum="ca995eb1a635c97393466f67aaec8e9e753b8ed5", sha256sum= "1c4baac658fd56e6ec9cca37f440a4bd8c9c0b02a21f41b30b8ea17b402a1907", arch="i386", epoch="0", name="gnu-efi-debuginfo", release="1.1", repository_memberships=[ "fake-repository-id-1", "fake-repository-id-2" ], sourcerpm="gnu-efi-3.0c-1.1.src.rpm", version="3.0c", ), ]
def test_remove_filtered_content(): """repo.remove_content() succeeds and removes expected units inserted via controller.""" controller = FakeController() client = controller.client rpm_units = [ RpmUnit(name="bash", version="4.0", release="1", arch="x86_64"), RpmUnit(name="glibc", version="5.0", release="1", arch="x86_64"), ] modulemd_units = [ ModulemdUnit(name="module1", stream="s1", version=1234, context="a1b2", arch="x86_64"), ModulemdUnit(name="module1", stream="s1", version=1235, context="a1b2", arch="x86_64"), ] units = rpm_units + modulemd_units repo = YumRepository(id="repo1") controller.insert_repository(repo) controller.insert_units(repo, units) criteria = Criteria.and_(Criteria.with_unit_type(RpmUnit), Criteria.with_field("name", "bash")) remove_rpms = client.get_repository("repo1").remove_content( criteria=criteria) assert len(remove_rpms) == 1 task = remove_rpms[0] # It should have completed successfully assert task.completed assert task.succeeded # It should have removed the specific rpm assert len(task.units) == 1 assert task.units[0] == sorted(rpm_units)[0] # Try removing a module with incorrect type_ids criteria = Criteria.and_(Criteria.with_unit_type(RpmUnit), Criteria.with_field("name", "module1")) remove_rpms = client.get_repository("repo1").remove_content( criteria=criteria) assert len(remove_rpms) == 1 task = remove_rpms[0] # It should have completed successfully assert task.completed assert task.succeeded # Nothing's removed as criteria isn't fulfilled assert len(task.units) == 0 # Removing module with correct type_ids criteria = Criteria.and_(Criteria.with_unit_type(ModulemdUnit), Criteria.with_field("name", "module1")) remove_rpms = client.get_repository("repo1").remove_content( criteria=criteria) assert len(remove_rpms) == 1 task = remove_rpms[0] # It should have completed successfully assert task.completed assert task.succeeded # It should have removed both the modules as they # match the criteria assert len(task.units) == 2 assert sorted(task.units) == sorted(modulemd_units)
def test_unit_type_invalid(): """Criteria.with_unit_type raises if provided value isn't a unit subclass.""" with pytest.raises(TypeError) as exc_info: Criteria.with_unit_type([1, 2, 3]) assert "Expected a Unit type, got: [1, 2, 3]" in str(exc_info.value)