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))
예제 #3
0
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)
예제 #4
0
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
예제 #5
0
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()
예제 #6
0
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)