def test_can_remove_content(): """repo.remove() 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) remove_rpms = client.get_repository("repo1").remove_content(type_ids=["rpm"]) assert len(remove_rpms) == 1 task = remove_rpms[0] # It should have completed successfully assert task.completed assert task.succeeded # It should have removed (only) RPM units assert sorted(task.units) == sorted(rpm_units) # Now if we ask to remove same content again... remove_rpms = client.get_repository("repo1").remove_content(type_ids=["rpm"]) assert len(remove_rpms) == 1 task = remove_rpms[0] # It should have completed successfully, but no RPMs to remove assert task.completed assert task.succeeded assert not task.units # It should still be possible to remove other content remove_all = client.get_repository("repo1").remove_content() assert len(remove_all) == 1 task = remove_all[0] # It should have completed successfully, and removed the modulemds assert task.completed assert task.succeeded assert sorted(task.units) == sorted(modulemd_units)
def test_update_checks_state(): """Update fails if update apparently succeeded in pulp client, yet the item doesn't match the desired state.""" pulp_unit = FileUnit( unit_id="some-file-unit", path="some/file.txt", size=5, sha256sum= "49ae93732fcf8d63fe1cce759664982dbd5b23161f007dba8561862adc96d063", description="a test file", repository_memberships=["some-repo"], ) pulp_ctrl = FakeController() repo = FileRepository(id="some-repo") pulp_ctrl.insert_repository(repo) pulp_ctrl.insert_units(repo, [pulp_unit]) item = NeverUpToDateItem( pushsource_item=FilePushItem( name="some/file.txt", sha256sum= "49ae93732fcf8d63fe1cce759664982dbd5b23161f007dba8561862adc96d063", dest=["some-repo"], ), pulp_unit=pulp_unit, pulp_state=State.NEEDS_UPDATE, ) # Try updating it. update_f = item.ensure_uptodate(pulp_ctrl.client) # The update attempt should fail. exc = update_f.exception() # It should tell us why. assert ( "item supposedly updated successfully, but actual and desired state still differ:" in str(exc)) # It should tell us the item we failed to process. assert "item: FilePushItem(name='some/file.txt'" in str(exc) # It should show the current and desired field values: # The 'current unit', i.e. the state after we updated, reversed the original # description. assert re.search(r"current unit: FileUnit.*elif tset a", str(exc)) # The 'desired unit', i.e. the reason we still don't consider the unit up-to-date, # wants to reverse the description back again... assert re.search(r"desired unit: FileUnit.*a test file", str(exc))
def test_remove_fails_without_type_id(): """repo.remove_content() fails when a criteria is provided without unit type""" 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"), ] repo = YumRepository(id="repo1") controller.insert_repository(repo) controller.insert_units(repo, rpm_units) criteria = Criteria.and_(Criteria.with_field("name", "bash")) with pytest.raises(ValueError): client.get_repository("repo1").remove_content(criteria=criteria)
def test_can_insert_orphans(): """insert_units with a null repo inserts units as orphans.""" controller = FakeController() units = [ FileUnit( path="bar", size=0, sha256sum= "b1a6cb41223dcd02f208827517fe4b59a12684b76e15dbee645e9f9a9daa952e", ), FileUnit( path="quux", size=0, sha256sum= "b1a6cb41223dcd02f208827517fe4b59a12684b76e15dbee645e9f9a9daa952e", ), ] # Can insert controller.insert_units(None, units) client = controller.client # If I now search for all content... found = list(client.search_content()) for unit in found: # It should have an ID assert unit.unit_id # It should have memberships [] (no repos) rather than None (unknown repos) assert unit.repository_memberships == [] # Other than those two fields, it should be identical to the input found_cmp = [ attr.evolve(u, unit_id=None, repository_memberships=None) for u in found ] assert sorted(found_cmp, key=repr) == units
class PersistentFake(object): """Wraps pulplib fake client adding persistence of state.""" def __init__(self, state_path): self.ctrl = FakeController() self.state_path = state_path # Register ourselves with pubtools so we can get the task stop hook, # at which point we will save our current state. pm.register(self) def load_initial(self): """Initial load of data into the fake, in the case where no state has previously been persisted. This will populate a hardcoded handful of repos which are expected to always be present in a realistically configured rhsm-pulp server. """ self.ctrl.insert_repository(FileRepository(id="redhat-maintenance")) self.ctrl.insert_repository(FileRepository(id="all-iso-content")) self.ctrl.insert_repository(YumRepository(id="all-rpm-content")) def load(self): """Load data into the fake from previously serialized state (if any). If no state has been previously serialized, load_initial will be used to seed the fake with some hardcoded state. """ if not os.path.exists(self.state_path): return self.load_initial() with open(self.state_path, "rt") as f: # pylint:disable=unspecified-encoding raw = yaml.load(f, Loader=yaml.SafeLoader) repos = raw.get("repos") or [] for repo in deserialize(repos): self.ctrl.insert_repository(repo) units = raw.get("units") or [] for unit in deserialize(units): for repo_id in unit.repository_memberships: repo = self.ctrl.client.get_repository(repo_id).result() self.ctrl.insert_units(repo, [unit]) def save(self): """Serialize the current state of the fake and save it to persistent storage.""" serialized = {} serialized["repos"] = serialize(self.ctrl.repositories) serialized["repos"].sort(key=lambda repo: repo["id"]) all_units = list(self.ctrl.client.search_content()) serialized["units"] = serialize(all_units) # This sort key is a bit expensive since it means we essentially do yaml dump # twice. On the plus side it ensures a stable order across py2 and py3. serialized["units"].sort( key=lambda x: yaml.dump(x, Dumper=yaml.SafeDumper)) path = self.state_path state_dir = os.path.dirname(path) if not os.path.isdir(state_dir): os.makedirs(state_dir) with open(path, "wt") as f: # pylint:disable=unspecified-encoding yaml.dump(serialized, f, Dumper=yaml.SafeDumper) LOG.info("Fake pulp state persisted to %s", path) @hookimpl def task_stop(self, failed): # pylint:disable=unused-argument """Called when a task is ending.""" pm.unregister(self) self.save()
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)