def populated_repo(controller):
    units = [
        RpmUnit(name="bash", version="4.0", release="1", arch="x86_64"),
        RpmUnit(content_type_id="srpm",
                name="bash",
                version="4.0",
                release="1",
                arch="src"),
        RpmUnit(
            name="glibc",
            version="5.0",
            release="1",
            arch="x86_64",
            sourcerpm="glibc-5.0-1.el5_11.1.src.rpm",
        ),
        ModulemdUnit(name="module1",
                     stream="s1",
                     version=1234,
                     context="a1b2",
                     arch="x86_64"),
        ModulemdUnit(name="module2",
                     stream="s2",
                     version=1234,
                     context="a1b2",
                     arch="x86_64"),
        ErratumUnit(id="RHBA-1234:56", summary="The best advisory"),
    ]

    repo = YumRepository(id="repo1")
    controller.insert_repository(repo)
    controller.insert_units(repo, units)

    return controller.client.get_repository(repo.id).result()
def unit_for_item(item, old_unit):
    assert isinstance(item, ErratumPushItem)

    return ErratumUnit(
        # Fields which are plainly copied
        id=item.name,
        status=item.status,
        updated=item.updated,
        issued=item.issued,
        description=item.description,
        pushcount=item.pushcount,
        reboot_suggested=item.reboot_suggested,
        from_=item.from_,
        rights=item.rights,
        title=item.title,
        severity=item.severity,
        release=item.release,
        type=item.type,
        solution=item.solution,
        summary=item.summary,
        content_types=item.content_types,
        # This field needs to be bumped if there is an existing unit,
        # else Pulp will discard changes.
        version=unit_erratum_version(item, old_unit),
        # These types need some conversions applied.
        references=unit_erratum_references(item),
        pkglist=unit_erratum_pkglist(item),
    )
def test_erratum_publishes_all_repos():
    item = PulpErratumPushItem(
        # We're being asked to push an advisory to a few repos...
        pushsource_item=ErratumPushItem(name="RHSA-1234:56",
                                        dest=["new1", "new2", "existing1"]),
        pulp_state=State.PARTIAL,
        pulp_unit=ErratumUnit(
            id="abc123",
            # ...and the advisory already exists in some Pulp, repos, maybe with
            # some overlap
            repository_memberships=[
                "all-rpm-content",
                "all-rpm-content-ff",
                "existing1",
                "existing2",
            ],
        ),
    )

    # Then when we calculate the repos which should be published for this item,
    # it should always include both the new repo(s) we're pushing to and also the
    # existing repos, as any mutation of the erratum requires metadata to be
    # republished for all of them.
    # all-rpm-content is an exception given that those repos don't get published.
    assert item.publish_pulp_repos == [
        "existing1", "existing2", "new1", "new2"
    ]
Beispiel #4
0
def test_upload_overwrite_noop():
    """repo.upload_erratum() doesn't overwrite erratum unit if version is unmodified."""

    controller = FakeController()

    controller.insert_repository(YumRepository(id="repo1"))
    controller.insert_repository(YumRepository(id="repo2"))

    client = controller.client
    repo1 = client.get_repository("repo1").result()
    repo2 = client.get_repository("repo2").result()

    to_upload1 = ErratumUnit(id="RHBA-1234:56",
                             summary="test advisory",
                             version="3")
    to_upload2 = ErratumUnit(
        id="RHBA-1234:56",
        summary="updated test advisory",
        description="changed it, but no effect due to same version",
        version="3",
    )

    # Upload the advisory to two different repos.
    assert repo1.upload_erratum(to_upload1).result()
    assert repo2.upload_erratum(to_upload2).result()

    # Now let's check the outcome in each repo (and entire system).
    units_repo1 = sorted(repo1.search_content(), key=repr)
    units_repo2 = sorted(repo2.search_content(), key=repr)
    units_all = sorted(client.search_content(), key=repr)

    # What we expect to see is that we only have one advisory (as only
    # a single id was used), that advisory is present in two repos, and
    # the advisory content is equal to the first upload because version
    # was not bumped for the second upload.

    assert units_repo1 == [
        ErratumUnit(
            unit_id="e3e70682-c209-4cac-629f-6fbed82c07cd",
            id="RHBA-1234:56",
            summary="test advisory",
            version="3",
            repository_memberships=["repo1", "repo2"],
        )
    ]
    assert units_repo2 == units_repo1
    assert units_all == units_repo1
Beispiel #5
0
def test_can_upload_units():
    """repo.upload_erratum() succeeds with fake client and populates units."""

    controller = FakeController()

    controller.insert_repository(YumRepository(id="repo1"))

    client = controller.client
    repo1 = client.get_repository("repo1").result()

    to_upload = ErratumUnit(
        id="RHBA-1234:56",
        summary="test advisory",
        # Add some existing memberships in an attempt to screw it up...
        # (they should not affect the upload)
        repository_memberships=["repo2", "repo3"],
    )

    upload_f = repo1.upload_erratum(to_upload)

    # Upload should complete successfully.
    tasks = upload_f.result()

    # At least one task.
    assert tasks

    # Every task should have succeeded.
    for t in tasks:
        assert t.succeeded

    # If I now search for content in that repo, or content across all repos...
    units_in_repo = list(repo1.search_content())
    units_all = list(client.search_content())

    # They should be equal
    assert units_all == units_in_repo

    # And they should be this
    assert units_in_repo == [
        ErratumUnit(
            unit_id="e3e70682-c209-4cac-629f-6fbed82c07cd",
            id="RHBA-1234:56",
            summary="test advisory",
            repository_memberships=["repo1"],
        )
    ]
def test_search_erratum_by_type(populated_repo):
    """search_content for erratum returns matching content"""

    crit = Criteria.with_field("content_type_id", "erratum")
    units = list(populated_repo.search_content(crit))
    assert units == [
        ErratumUnit(
            unit_id="85776e9a-dd84-f39e-7154-5a137a1d5006",
            id="RHBA-1234:56",
            summary="The best advisory",
            repository_memberships=["repo1"],
        )
    ]
Beispiel #7
0
def _setup_controller(controller):
    # add repo
    repo = YumRepository(
        id="repo",
        eng_product_id=101,
        distributors=[],
        relative_url="content/unit/1/client",
        mutable_urls=["mutable1", "mutable2"],
    )
    nochannel_repo = YumRepository(
        id="all-rpm-content",
        eng_product_id=100,
        distributors=[],
        relative_url="content/unit/1/all-rpm",
        mutable_urls=["mutable1", "mutable2"],
    )
    # add unit
    erratum = ErratumUnit(
        id="RHSA-1234:56",
        version="2",
        content_types=["rpm", "module"],
        references=[
            ErratumReference(
                title="title",
                href="https://example.com/test-advisory",
                type="self",
                id="self-id",
            ),
            ErratumReference(
                title="CVE-123",
                href="https://example.com/test-cve",
                type="cve",
                id="CVE-123",
            ),
        ],
        pkglist=[],
        repository_memberships=["repo", "all-rpm-content"],
    )

    controller.insert_repository(repo)
    controller.insert_repository(nochannel_repo)
    controller.insert_units(repo, [erratum])
    controller.insert_units(nochannel_repo, [erratum])
def test_erratum_validates_references():
    """It is not possible to pass incorrect types into an erratum reference list."""

    # Validation of references within the list is tested explicitly because deep
    # validation is uncommon across the model. We don't explicitly test it for every
    # field though.

    unit = ErratumUnit(id="RHBA-1234:56")
    ref = ErratumReference(href="https://example.com")

    # It starts out with absent references.
    assert unit.references is None

    # We can add an empty list OK...
    assert evolve(unit, references=[]).references == []

    # We can add a list with references OK...
    assert evolve(unit, references=[ref]).references == [ref]

    # But we cannot add a list with other stuff
    with pytest.raises(TypeError):
        evolve(unit, references=[ref, {"href": "abc123"}])
Beispiel #9
0
def test_delete_advisory(command_tester, fake_collector, monkeypatch):
    """Deletion of packages and modules in advisories from provided repos succeeds"""

    repo1 = YumRepository(id="some-yumrepo",
                          relative_url="some/publish/url",
                          mutable_urls=["repomd.xml"])
    repo2 = YumRepository(
        id="some-other-repo",
        relative_url="other/publish/url",
        mutable_urls=["repomd.xml"],
    )

    pkglist = [
        ErratumPackageCollection(
            name="colection-0",
            packages=None,
            short="",
            module=ErratumModule(name="mymod",
                                 stream="s1",
                                 version="123",
                                 context="a1c2",
                                 arch="s390x"),
        ),
        ErratumPackageCollection(
            name="collection-1",
            packages=[
                ErratumPackage(
                    name="bash",
                    version="1.23",
                    release="1.test8",
                    arch="x86_64",
                    filename="bash-1.23-1.test8_x86_64.rpm",
                    sha256sum="a" * 64,
                    md5sum="b" * 32,
                ),
                ErratumPackage(
                    name="dash",
                    version="1.23",
                    release="1.test8",
                    arch="x86_64",
                    filename="dash-1.23-1.test8_x86_64.rpm",
                    sha256sum="a" * 64,
                    md5sum="b" * 32,
                ),
            ],
            short="",
            module=None,
        ),
    ]

    files1 = [
        RpmUnit(
            name="bash",
            version="1.23",
            release="1.test8",
            arch="x86_64",
            filename="bash-1.23-1.test8_x86_64.rpm",
            sha256sum="a" * 64,
            md5sum="b" * 32,
            signing_key="aabbcc",
            unit_id="files1_rpm1",
        ),
        RpmUnit(
            name="dash",
            version="1.23",
            release="1.test8",
            arch="x86_64",
            filename="dash-1.23-1.test8_x86_64.rpm",
            sha256sum="a" * 64,
            md5sum="b" * 32,
            signing_key="aabbcc",
            unit_id="files1_rpm2",
        ),
        RpmUnit(
            name="crash",
            version="1.23",
            release="1.test8",
            arch="x86_64",
            filename=
            "crash-1.23-1.test8.module+el8.0.0+3049+59fd2bba.x86_64.rpm",
            sha256sum="a" * 64,
            md5sum="b" * 32,
            signing_key="aabbcc",
            unit_id="files1_rpm3",
        ),
        ModulemdUnit(
            name="mymod",
            stream="s1",
            version=123,
            context="a1c2",
            arch="s390x",
            artifacts=[
                "crash-0:1.23-1.test8.module+el8.0.0+3049+59fd2bba.x86_64"
            ],
            unit_id="files1_mod1",
        ),
        ErratumUnit(
            unit_id="e3e70682-c209-4cac-629f-6fbed82c07cd",
            id="RHSA-1111:22",
            summary="Dummy erratum",
            content_type_id="erratum",
            repository_memberships=["some-yumrepo"],
            pkglist=pkglist,
        ),
    ]

    files2 = [
        ErratumUnit(
            unit_id="x4e73262-e239-44ac-629f-6fbed82c07cd",
            id="RHBA-1001:22",
            summary="Other erratum",
            content_type_id="erratum",
            repository_memberships=["some-other-repo"],
            pkglist=[],
        ),
    ]

    with FakeDeleteAdvisory() as task_instance:

        task_instance.pulp_client_controller.insert_repository(repo1)
        task_instance.pulp_client_controller.insert_repository(repo2)
        task_instance.pulp_client_controller.insert_units(repo1, files1)
        task_instance.pulp_client_controller.insert_units(repo2, files2)

        # Let's try setting the cache flush root via env.
        monkeypatch.setenv("FASTPURGE_ROOT_URL", "https://cdn.example2.com/")

        # It should run with expected output.
        command_tester.test(
            task_instance.main,
            [
                "test-delete",
                "--pulp-url",
                "https://pulp.example.com/",
                "--fastpurge-host",
                "fakehost-xxx.example.net",
                "--fastpurge-client-secret",
                "abcdef",
                "--fastpurge-client-token",
                "efg",
                "--fastpurge-access-token",
                "tok",
                "--repo",
                "some-yumrepo,other-yumrepo",
                "--advisory",
                "RHSA-1111:22",
                "--advisory",
                "RHBA-1001:22",
            ],
        )

        assert sorted(fake_collector.items, key=lambda pi: pi["filename"]) == [
            {
                "origin": "pulp",
                "src": None,
                "dest": "some-yumrepo",
                "signing_key": None,
                "filename": "bash-1.23-1.test8.x86_64.rpm",
                "state": "DELETED",
                "build": None,
                "checksums": {
                    "sha256": "a" * 64
                },
            },
            {
                "origin": "pulp",
                "src": None,
                "dest": "some-yumrepo",
                "signing_key": None,
                "filename": "crash-1.23-1.test8.x86_64.rpm",
                "state": "DELETED",
                "build": None,
                "checksums": {
                    "sha256": "a" * 64
                },
            },
            {
                "origin": "pulp",
                "src": None,
                "dest": "some-yumrepo",
                "signing_key": None,
                "filename": "dash-1.23-1.test8.x86_64.rpm",
                "state": "DELETED",
                "build": None,
                "checksums": {
                    "sha256": "a" * 64
                },
            },
            {
                "origin": "pulp",
                "src": None,
                "dest": "some-yumrepo",
                "signing_key": None,
                "filename": "mymod:s1:123:a1c2:s390x",
                "state": "DELETED",
                "build": None,
                "checksums": None,
            },
        ]

        # verify whether the rpms and modules were deleted from the repo on Pulp
        client = task_instance.pulp_client

        # effectively only some-yumrepo(repo1) was modified
        repos = list(
            client.search_repository(
                Criteria.with_id("some-yumrepo")).result())
        assert len(repos) == 1
        repo = repos[0]

        # list the removed unit's unit_id
        # RPMs from the erratum package list
        unit_ids = ["files1_rpm1", "files1_rpm2"]
        # module from the erratum package list
        unit_ids.append("files1_mod1")
        # package in the above module
        unit_ids.append("files1_rpm3")
        criteria = Criteria.with_field("unit_id", Matcher.in_(unit_ids))

        # deleted files are not in the repo
        files = list(repo.search_content(criteria).result())
        assert len(files) == 0

        # same files exist on Pulp as orphans
        files_search = list(client.search_content(criteria).result())
        assert len(files_search) == 4
Beispiel #10
0
def test_update_push(fake_controller, data_path, fake_push, fake_state_path,
                     command_tester, monkeypatch):
    """Test a more complex push where items already exist in Pulp in a variety of
    different states.
    """

    # For this test we'll force an abnormally small queue size.
    # This will verify that nothing breaks in edge cases such as the queue size
    # being smaller than the batch size.
    monkeypatch.setattr(context, "QUEUE_SIZE", 2)

    # Sanity check that the Pulp server is, initially, empty.
    client = fake_controller.client
    assert list(client.search_content()) == []

    all_rpm_content = client.get_repository("all-rpm-content").result()
    iso_dest1 = client.get_repository("iso-dest1").result()
    dest1 = client.get_repository("dest1").result()

    # Make this RPM exist, but not in all the desired repos.
    existing_rpm = RpmUnit(
        cdn_published=datetime.datetime(2021, 12, 14, 9, 59),
        arch="src",
        filename="test-srpm01-1.0-1.src.rpm",
        md5sum="ba9257ced24f77f4d777e399e67924f5",
        name="test-srpm01",
        version="1.0",
        release="1",
        provides=[],
        requires=[
            RpmDependency(
                epoch="0",
                version="4.6.0",
                release="1",
                flags="LE",
                name="rpmlib(FileDigests)",
            ),
            RpmDependency(
                epoch="0",
                version="3.0.4",
                release="1",
                flags="LE",
                name="rpmlib(CompressedFileNames)",
            ),
        ],
        sha1sum="d9629c034fed3a2f47870fc6fdc78a30c5556e1d",
        sha256sum=
        "54cc4713fe704dfc7a4fd5b398f834ceb6a692f53b0c6aefaf89d88417b4c51d",
        unit_id="existing-rpm-id1",
    )
    fake_controller.insert_units(all_rpm_content, [existing_rpm])

    # Make this file exist, but with an outdated description.
    existing_file = FileUnit(
        cdn_path=
        "/content/origin/files/sha256/db/db68c8a70f8383de71c107dca5fcfe53b1132186d1a6681d9ee3f4eea724fabb/some-iso",
        cdn_published=datetime.datetime(2021, 12, 14, 9, 59),
        description="A wrong description",
        path="some-iso",
        sha256sum=
        "db68c8a70f8383de71c107dca5fcfe53b1132186d1a6681d9ee3f4eea724fabb",
        size=46,
        unit_id="existing-file-id1",
    )
    fake_controller.insert_units(iso_dest1, [existing_file])

    # Make this file exist, but in no repos at all, making it an orphan
    orphan_file = FileUnit(
        cdn_path=
        "/content/origin/files/sha256/d8/d8301c5f72f16455dbc300f3d1bef8972424255caad103cc6c7ba7dc92d90ca8/test.txt",
        cdn_published=datetime.datetime(2021, 12, 14, 9, 59),
        path="test.txt",
        sha256sum=
        "d8301c5f72f16455dbc300f3d1bef8972424255caad103cc6c7ba7dc92d90ca8",
        size=33,
        unit_id="orphan-file-id1",
    )
    fake_controller.insert_units(None, [orphan_file])

    # Make this erratum exist, but with most fields missing
    existing_erratum = ErratumUnit(
        id="RHSA-2020:0509",
        unit_id="existing-erratum-id1",
        # make this have a non-integral version right now so usual bumping
        # does not work
        version="oops-not-integer",
    )
    fake_controller.insert_units(dest1, [existing_erratum])

    # Set it up to find content from our staging dir, which contains a mixture
    # of just about every content type
    stagedir = os.path.join(data_path, "staged-mixed")

    compare_extra = {
        "pulp.yaml": {
            "filename": fake_state_path,
            "normalize": hide_unit_ids,
        }
    }
    args = [
        "",
        "--source",
        "staged:%s" % stagedir,
        "--allow-unsigned",
        "--pulp-url",
        "https://pulp.example.com/",
    ]

    run = functools.partial(entry_point, cls=lambda: fake_push)

    # It should be able to run without crashing.
    command_tester.test(
        run,
        args,
        compare_plaintext=False,
        compare_jsonl=False,
        # This will ensure the Pulp state matches the baseline.
        compare_extra=compare_extra,
    )

    # Pulp state is covered by compare_extra, but let's also explicitly compare
    # the changes we expect on those existing units...

    updated_rpm = list(
        client.search_content(
            Criteria.with_field("unit_id", existing_rpm.unit_id)))
    assert len(updated_rpm) == 1
    updated_rpm = updated_rpm[0]

    updated_file = list(
        client.search_content(
            Criteria.with_field("unit_id", existing_file.unit_id)))
    assert len(updated_file) == 1
    updated_file = updated_file[0]

    updated_orphan_file = list(
        client.search_content(
            Criteria.with_field("unit_id", orphan_file.unit_id)))
    assert len(updated_orphan_file) == 1
    updated_orphan_file = updated_orphan_file[0]

    updated_erratum = list(
        client.search_content(
            Criteria.with_field("unit_id", existing_erratum.unit_id)))
    assert len(updated_erratum) == 1
    updated_erratum = updated_erratum[0]

    # RPM after push should be as it was before except that dest1 was added into
    # repository_memberships.
    assert updated_rpm == attr.evolve(
        existing_rpm, repository_memberships=["all-rpm-content", "dest1"])

    # File after push should be as it was before except that description was updated
    # to the desired value.
    assert updated_file == attr.evolve(updated_file,
                                       description="My wonderful ISO")

    # Orphaned file after push should be as it was before except no longer an orphan.
    assert updated_orphan_file == attr.evolve(
        orphan_file,
        repository_memberships=["iso-dest1", "iso-dest2"],
    )

    # Erratum after push should be updated. The full update will not be tested here
    # as it's extremely verbose, we'll just sample some fields. But, critically,
    # the 'version' field (which was not an integer in pulp) should have been
    # simply overwritten with the input rather than bumped.
    assert updated_erratum.title == "Important: sudo security update"
    assert updated_erratum.pkglist
    assert updated_erratum.version == "3"
Beispiel #11
0
 def u(version=None):
     return ErratumUnit(id="whatever", version=version)
Beispiel #12
0
def test_upload_overwrite():
    """repo.upload_erratum() can overwrite fields of an existing advisory."""

    controller = FakeController()

    controller.insert_repository(YumRepository(id="repo1"))
    controller.insert_repository(YumRepository(id="repo2"))

    client = controller.client
    repo1 = client.get_repository("repo1").result()
    repo2 = client.get_repository("repo2").result()

    to_upload1 = ErratumUnit(id="RHBA-1234:56",
                             summary="test advisory",
                             version="1")
    to_upload2 = ErratumUnit(
        id="RHBA-1234:56",
        summary="updated test advisory",
        description="I've altered the deal",
        version="2",
    )
    to_upload3 = ErratumUnit(id="RHBA-1234:57", summary="a different advisory")

    # Upload all three of the above advisories.
    # Uploads 1 and 2 are for the same advisory (though we use
    # different repos to see what happens).
    assert repo1.upload_erratum(to_upload1).result()
    assert repo2.upload_erratum(to_upload2).result()
    assert repo2.upload_erratum(to_upload3).result()

    # Now let's check the outcome in each repo (and entire system).
    units_repo1 = sorted(repo1.search_content(), key=repr)
    units_repo2 = sorted(repo2.search_content(), key=repr)
    units_all = sorted(client.search_content(), key=repr)

    # What we expect to see is that the three uploads resulted in only
    # two errata, with the fields on the first advisory set to the values
    # after the most recent upload of it, and the second advisory equal to
    # the single upload for that advisory. Also, the first advisory is
    # now present in two repos.

    assert units_repo1 == [
        ErratumUnit(
            unit_id="e3e70682-c209-4cac-629f-6fbed82c07cd",
            id="RHBA-1234:56",
            summary="updated test advisory",
            description="I've altered the deal",
            version="2",
            repository_memberships=["repo1", "repo2"],
        )
    ]
    assert units_repo2 == [
        ErratumUnit(
            unit_id="e3e70682-c209-4cac-629f-6fbed82c07cd",
            id="RHBA-1234:56",
            summary="updated test advisory",
            description="I've altered the deal",
            version="2",
            repository_memberships=["repo1", "repo2"],
        ),
        ErratumUnit(
            unit_id="e6f4590b-9a16-4106-cf6a-659eb4862b21",
            id="RHBA-1234:57",
            summary="a different advisory",
            repository_memberships=["repo2"],
        ),
    ]

    assert units_repo2 == units_all
 def make_erratum_unit(self, metadata):
     md = metadata.copy()
     md["_id"] = self.next_unit_id()
     md["_content_type_id"] = "erratum"
     return ErratumUnit.from_data(md)
Beispiel #14
0
def test_can_load_erratum(data_path):
    """ErratumUnit loads correctly from a complex sample Pulp response."""

    # This JSON was taken from a real Pulp search, though it was slightly trimmed
    # to reduce the size of the test data (e.g. cutting out modules for some arches,
    # cutting down the repo and package lists).
    with open(os.path.join(data_path, "sample-erratum.json"), "rt") as f:
        data = json.load(f)

    # It should parse correctly
    loaded = Unit.from_data(data)

    # It should be equal to the following...

    # Note, in order to make the test more manageable in case of failure, we verify
    # some of the more complicated nested fields first, then omit them from the
    # later comparison of the overall unit. This way the pytest output is more amenable
    # to copy-pasting values back into the test if behavior changes.
    assert loaded.references == [
        ErratumReference(
            href="https://access.redhat.com/errata/RHSA-2019:0975",
            id="RHSA-2019:0975",
            title="RHSA-2019:0975",
            type="self",
        ),
        ErratumReference(
            href="https://bugzilla.redhat.com/show_bug.cgi?id=1664908",
            id="1664908",
            title=
            "CVE-2019-5736 runc: Execution of malicious containers allows for container escape and access to host filesystem",
            type="bugzilla",
        ),
        ErratumReference(
            href="https://bugzilla.redhat.com/show_bug.cgi?id=1695689",
            id="1695689",
            title=
            "[stream rhel8] don't allow a container to connect to random services",
            type="bugzilla",
        ),
        ErratumReference(
            href="https://www.redhat.com/security/data/cve/CVE-2019-5736.html",
            id="CVE-2019-5736",
            title="CVE-2019-5736",
            type="cve",
        ),
        ErratumReference(
            href=
            "https://access.redhat.com/security/updates/classification/#important",
            id="classification",
            title="important",
            type="other",
        ),
    ]

    assert loaded.pkglist == [
        ErratumPackageCollection(
            name="collection-0",
            packages=[
                ErratumPackage(
                    arch="x86_64",
                    filename=
                    "slirp4netns-debuginfo-0.1-2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551.x86_64.rpm",
                    epoch="0",
                    name="slirp4netns-debuginfo",
                    version="0.1",
                    release="2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="917ceef4aba550095d6ce5ab72b20e2e",
                    sha1sum=None,
                    sha256sum=
                    "c4de28590622f59415de3a8b9fcb427cfd34637c4a7e6accd29d3f39d7699e6d",
                ),
                ErratumPackage(
                    arch="x86_64",
                    filename=
                    "slirp4netns-debugsource-0.1-2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551.x86_64.rpm",
                    epoch="0",
                    name="slirp4netns-debugsource",
                    version="0.1",
                    release="2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="9519596175f7eb90439f4f60db38e97d",
                    sha1sum=None,
                    sha256sum=
                    "d0f48388b6ba9d62d2350cd4216755f2517aaa3934663e2fc192b2f40c615e49",
                ),
                ErratumPackage(
                    arch="x86_64",
                    filename=
                    "slirp4netns-0.1-2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551.x86_64.rpm",
                    epoch="0",
                    name="slirp4netns",
                    version="0.1",
                    release="2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="af0d6447dc9f81d2718e70f103070bc0",
                    sha1sum=None,
                    sha256sum=
                    "e7a6c321ae08e6050c39d5a0c94d6e765c1a9d4d2b030f219bf6d916619b29f1",
                ),
                ErratumPackage(
                    arch="SRPMS",
                    filename=
                    "slirp4netns-0.1-2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551.src.rpm",
                    epoch="0",
                    name="slirp4netns",
                    version="0.1",
                    release="2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="c863064c1edd9f5d78208e873692c9dd",
                    sha1sum=None,
                    sha256sum=
                    "be2d49e797db6395e819335ea8debe2639d562a621c730604b38139961d9d05b",
                ),
                ErratumPackage(
                    arch="x86_64",
                    filename=
                    "skopeo-debugsource-0.1.32-3.git1715c90.module+el8.0.0+2958+4e823551.x86_64.rpm",
                    epoch="1",
                    name="skopeo-debugsource",
                    version="0.1.32",
                    release="3.git1715c90.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="6ee19888b7b3f900063331c75f9c4ab6",
                    sha1sum=None,
                    sha256sum=
                    "71a82a595c93c9aef8c316fd87937e0334af51e2fc2996970ce39285daf03053",
                ),
                ErratumPackage(
                    arch="x86_64",
                    filename=
                    "skopeo-0.1.32-3.git1715c90.module+el8.0.0+2958+4e823551.x86_64.rpm",
                    epoch="1",
                    name="skopeo",
                    version="0.1.32",
                    release="3.git1715c90.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="b6ae238c20daf85543d25daa292f83a7",
                    sha1sum=None,
                    sha256sum=
                    "59070bd8647cdb34f434ef1a5593ff727ab87a0df105417de0bf16a2b5232512",
                ),
                ErratumPackage(
                    arch="x86_64",
                    filename=
                    "runc-debugsource-1.0.0-55.rc5.dev.git2abd837.module+el8.0.0+3049+59fd2bba.x86_64.rpm",
                    epoch="0",
                    name="runc-debugsource",
                    version="1.0.0",
                    release=
                    "55.rc5.dev.git2abd837.module+el8.0.0+3049+59fd2bba",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="eedf3c1be375ebbe727471f4c9a225d9",
                    sha1sum=None,
                    sha256sum=
                    "f408bd733935a79274bb810bd1cff00bca93fcfa410315b1e4f071ae177774e6",
                ),
            ],
            short="",
            module=ErratumModule(
                name="container-tools",
                stream="rhel8",
                version="8000020190416221845",
                context="2ffa3d27",
                arch="x86_64",
            ),
        ),
        ErratumPackageCollection(
            name="collection-3",
            packages=[
                ErratumPackage(
                    arch="SRPMS",
                    filename=
                    "slirp4netns-0.1-2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551.src.rpm",
                    epoch="0",
                    name="slirp4netns",
                    version="0.1",
                    release="2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="c863064c1edd9f5d78208e873692c9dd",
                    sha1sum="f3d9ae4aeea6946a8668445395ba10b7399523a0",
                    sha256sum=
                    "be2d49e797db6395e819335ea8debe2639d562a621c730604b38139961d9d05b",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "skopeo-debugsource-0.1.32-3.git1715c90.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="1",
                    name="skopeo-debugsource",
                    version="0.1.32",
                    release="3.git1715c90.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="76161e93a42383b4b6b1f42482f3dd4d",
                    sha1sum=None,
                    sha256sum=
                    "aea7d37b68d252d5e57d6db50b5c26188412d6464e0b81a5a6deae431ea55bee",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "skopeo-debuginfo-0.1.32-3.git1715c90.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="1",
                    name="skopeo-debuginfo",
                    version="0.1.32",
                    release="3.git1715c90.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="8004f3a05e5eac46c76a2e805be3809e",
                    sha1sum=None,
                    sha256sum=
                    "dda994b3f186ed3ce6a9d7c48402a0bab7757eb020b72991c9dd35e615b5e4eb",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "runc-debugsource-1.0.0-55.rc5.dev.git2abd837.module+el8.0.0+3049+59fd2bba.s390x.rpm",
                    epoch="0",
                    name="runc-debugsource",
                    version="1.0.0",
                    release=
                    "55.rc5.dev.git2abd837.module+el8.0.0+3049+59fd2bba",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="6b171a203c7bf91b8f0b78f453fcef9c",
                    sha1sum=None,
                    sha256sum=
                    "845de746c15d5bf7e29f5a13011066c968c1dfb05cd554b0450a2d25a7e4e3bc",
                ),
                ErratumPackage(
                    arch="SRPMS",
                    filename=
                    "runc-1.0.0-55.rc5.dev.git2abd837.module+el8.0.0+3049+59fd2bba.src.rpm",
                    epoch="0",
                    name="runc",
                    version="1.0.0",
                    release=
                    "55.rc5.dev.git2abd837.module+el8.0.0+3049+59fd2bba",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="364ba52d0e1eb8fbe899c3424520eb56",
                    sha1sum=None,
                    sha256sum=
                    "3a40f68a0b93dd2ac3cddf5b1d58ef77372942777fc798ff413453d6fa0253f7",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "slirp4netns-debuginfo-0.1-2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="slirp4netns-debuginfo",
                    version="0.1",
                    release="2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="797254858bba898ace72128df8d8ec3e",
                    sha1sum=None,
                    sha256sum=
                    "e169df356459146ceaa745297d8df49a3b15cc9e648b418869ca9e35020f3cac",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "runc-1.0.0-55.rc5.dev.git2abd837.module+el8.0.0+3049+59fd2bba.s390x.rpm",
                    epoch="0",
                    name="runc",
                    version="1.0.0",
                    release=
                    "55.rc5.dev.git2abd837.module+el8.0.0+3049+59fd2bba",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="25e8c8cd2ed9e0a0a02dc5aef09889a8",
                    sha1sum=None,
                    sha256sum=
                    "46bb4965c22bca3aadc383503a5e84d2879b19217830ee0d04f029aa0bf92f07",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "runc-debuginfo-1.0.0-55.rc5.dev.git2abd837.module+el8.0.0+3049+59fd2bba.s390x.rpm",
                    epoch="0",
                    name="runc-debuginfo",
                    version="1.0.0",
                    release=
                    "55.rc5.dev.git2abd837.module+el8.0.0+3049+59fd2bba",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="326c37fb3566e45dc014968e5374fa87",
                    sha1sum=None,
                    sha256sum=
                    "5db29f35f2f40cfada2231146a8f6d1e3f430722c0f8d43a2638259ff2627e3f",
                ),
                ErratumPackage(
                    arch="noarch",
                    filename=
                    "podman-docker-1.0.0-2.git921f98f.module+el8.0.0+2958+4e823551.noarch.rpm",
                    epoch="0",
                    name="podman-docker",
                    version="1.0.0",
                    release="2.git921f98f.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="ad952f9efc5f29afec5fb9530deb28b6",
                    sha1sum=None,
                    sha256sum=
                    "40d3190ed329073ed3454bb726a7452b1b3ba8cd87b7d78183e42e899d187a1d",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "podman-debugsource-1.0.0-2.git921f98f.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="podman-debugsource",
                    version="1.0.0",
                    release="2.git921f98f.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="30b56bf9f2be62a4eb2f04cb6b6fd21a",
                    sha1sum=None,
                    sha256sum=
                    "052278774a5459fea098ca1307756adf8f3039cac64aff3b8968ceb765618b09",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "podman-debuginfo-1.0.0-2.git921f98f.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="podman-debuginfo",
                    version="1.0.0",
                    release="2.git921f98f.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="1597e5db5b8b4019b3025c986286091e",
                    sha1sum=None,
                    sha256sum=
                    "af7a7ba25f770cdd7710d4fc9fbf03b9c42e48b8ec1012592a8c9dd4f67d8fa6",
                ),
                ErratumPackage(
                    arch="SRPMS",
                    filename=
                    "skopeo-0.1.32-3.git1715c90.module+el8.0.0+2958+4e823551.src.rpm",
                    epoch="1",
                    name="skopeo",
                    version="0.1.32",
                    release="3.git1715c90.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="3400331ed99d0400067f9aed159e1e0d",
                    sha1sum=None,
                    sha256sum=
                    "21dc81a5e23fee5345680ff6862536ae7390a0e9e91dba6fc667e1e60dde57d9",
                ),
                ErratumPackage(
                    arch="SRPMS",
                    filename=
                    "podman-1.0.0-2.git921f98f.module+el8.0.0+2958+4e823551.src.rpm",
                    epoch="0",
                    name="podman",
                    version="1.0.0",
                    release="2.git921f98f.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="c3da563d95ae856854e0db46bd92d98b",
                    sha1sum=None,
                    sha256sum=
                    "39757bdfbe409896cff75635e3afe6aea21b25c09aab0789961d6168e8c8bff6",
                ),
                ErratumPackage(
                    arch="SRPMS",
                    filename=
                    "containernetworking-plugins-0.7.4-3.git9ebe139.module+el8.0.0+2958+4e823551.src.rpm",
                    epoch="0",
                    name="containernetworking-plugins",
                    version="0.7.4",
                    release="3.git9ebe139.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="fdb5afbae0ad44795776d843f2defd76",
                    sha1sum=None,
                    sha256sum=
                    "44e465a362abb8357f2019057162d02226a510abc78c15c65a88d72c67dd53b5",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "containernetworking-plugins-0.7.4-3.git9ebe139.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="containernetworking-plugins",
                    version="0.7.4",
                    release="3.git9ebe139.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="cc9e5527550ebf573ad36c5092c19ffc",
                    sha1sum=None,
                    sha256sum=
                    "b212c36df71a20689079592f27a9d03870a623a11f51a9761f7973e659939f81",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "containernetworking-plugins-debugsource-0.7.4-3.git9ebe139.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="containernetworking-plugins-debugsource",
                    version="0.7.4",
                    release="3.git9ebe139.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="85a20df93f2b529ad239e00492b67cd7",
                    sha1sum=None,
                    sha256sum=
                    "3a0b84d25293ede8957c38dae236947cd508415a7f0b892ad205d8cdb37f35e1",
                ),
                ErratumPackage(
                    arch="SRPMS",
                    filename=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    epoch="2",
                    name="container-selinux",
                    version="2.94",
                    release="1.git1e99f1d.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="e4265aa655362fdf6cc0265a29dc3792",
                    sha1sum=None,
                    sha256sum=
                    "e014ffe8047a36c08ddfdaa4f96a09d954cef60c17c2c79a6dc0d72d4ba5770e",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "skopeo-0.1.32-3.git1715c90.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="1",
                    name="skopeo",
                    version="0.1.32",
                    release="3.git1715c90.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="d382120e5fdaaa24e405fbb5ee670451",
                    sha1sum=None,
                    sha256sum=
                    "501765be7912c9d08ab5c5f5752ecf73569536457cd3ee2ce0643f70d3991cde",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "podman-1.0.0-2.git921f98f.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="podman",
                    version="1.0.0",
                    release="2.git921f98f.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="69ce75e8b3f2a2271cd8f17b6b1db4b7",
                    sha1sum=None,
                    sha256sum=
                    "893044e6293c97fd33e55d57058505b012d5aada5ebfc25cc00aa6950160cd84",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "buildah-1.5-3.gite94b4f9.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="buildah",
                    version="1.5",
                    release="3.gite94b4f9.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="d63e2bc9c179ea8135b9fc7ce8f4e326",
                    sha1sum=None,
                    sha256sum=
                    "044fd3ab6a4231843c704998b61eb161839ae0c203ed2b0a9cbe0259f35bc65b",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "slirp4netns-debugsource-0.1-2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="slirp4netns-debugsource",
                    version="0.1",
                    release="2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="c2e8d125a5e2c65fef41cca893048400",
                    sha1sum=None,
                    sha256sum=
                    "a85891d07733c3e7b765229358d2cec33331731649265a105a7b742e5b0accfa",
                ),
                ErratumPackage(
                    arch="SRPMS",
                    filename=
                    "fuse-overlayfs-0.3-2.module+el8.0.0+2958+4e823551.src.rpm",
                    epoch="0",
                    name="fuse-overlayfs",
                    version="0.3",
                    release="2.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="b09d3edcc9350a269b6c4c4c277d270a",
                    sha1sum=None,
                    sha256sum=
                    "88c203351d6aae3f5a02ea46fc221be18d28e3c3f2c5ebd17bada049bdb9e4d8",
                ),
                ErratumPackage(
                    arch="noarch",
                    filename=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.noarch.rpm",
                    epoch="2",
                    name="container-selinux",
                    version="2.94",
                    release="1.git1e99f1d.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="f7d31e5f099bcdadf419239db840baa8",
                    sha1sum=None,
                    sha256sum=
                    "8a3a4eb8c3ee529e3b103ece6200517ff6834d24dab1d202e392347efedc254e",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "containernetworking-plugins-debuginfo-0.7.4-3.git9ebe139.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="containernetworking-plugins-debuginfo",
                    version="0.7.4",
                    release="3.git9ebe139.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="da26f260ae089792ec07a876f4dbf2bb",
                    sha1sum=None,
                    sha256sum=
                    "e78ffa580ea6daad1fd16c15aa3483f2d85f0c15d6ba23c4a372daaa4382e31f",
                ),
                ErratumPackage(
                    arch="SRPMS",
                    filename=
                    "buildah-1.5-3.gite94b4f9.module+el8.0.0+2958+4e823551.src.rpm",
                    epoch="0",
                    name="buildah",
                    version="1.5",
                    release="3.gite94b4f9.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="d2366a6349f28506bfd4fb0525b533d7",
                    sha1sum=None,
                    sha256sum=
                    "55756e48575e8cf7eab5021c8ecd788e66741287a6da6d4dc18ed005e22e3093",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "buildah-debuginfo-1.5-3.gite94b4f9.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="buildah-debuginfo",
                    version="1.5",
                    release="3.gite94b4f9.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="4c8460d1f71c6d574aeca973ad2e0d89",
                    sha1sum=None,
                    sha256sum=
                    "65c626e0d15440fb56e8e0489da3f1ccf1442f3ba6ebf3338eefdf7ee98cea89",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "slirp4netns-0.1-2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="slirp4netns",
                    version="0.1",
                    release="2.dev.gitc4e1bc5.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="41cec16504692c5bc462b7d5f8737087",
                    sha1sum=None,
                    sha256sum=
                    "0e9580680295adeba3bc9f033176492f881adb98cbe919b921b9ec9a74f80181",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "fuse-overlayfs-debuginfo-0.3-2.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="fuse-overlayfs-debuginfo",
                    version="0.3",
                    release="2.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="51c4b466077a37084d7fedfdda3f57ff",
                    sha1sum=None,
                    sha256sum=
                    "fddcdcf52fec789deb0d68d871cc3e9960ec4f1f0930c3275f188b5a968d93d1",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "fuse-overlayfs-debugsource-0.3-2.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="fuse-overlayfs-debugsource",
                    version="0.3",
                    release="2.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="ba7f2bac9de2bdf232187b9c543c47fc",
                    sha1sum=None,
                    sha256sum=
                    "c7b0b7de23a900d05fe4052614e68226b00f1252b505898e14da3382002c26ef",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "oci-systemd-hook-0.1.15-2.git2d0b8a3.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="1",
                    name="oci-systemd-hook",
                    version="0.1.15",
                    release="2.git2d0b8a3.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="122fc1079f4a05e0b2dee5e60dea3e54",
                    sha1sum=None,
                    sha256sum=
                    "593595e3005ea32cf2ca84c93e1cba832461b2854b003046f3bd59f2e331819b",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "fuse-overlayfs-0.3-2.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="0",
                    name="fuse-overlayfs",
                    version="0.3",
                    release="2.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="5eeec013645c903124089ceae13e6710",
                    sha1sum=None,
                    sha256sum=
                    "28211a39e8bbdaf8792fc4485699696e67f62a0c4a40fc22a9ac1b7399f8edf7",
                ),
                ErratumPackage(
                    arch="SRPMS",
                    filename=
                    "oci-systemd-hook-0.1.15-2.git2d0b8a3.module+el8.0.0+2958+4e823551.src.rpm",
                    epoch="1",
                    name="oci-systemd-hook",
                    version="0.1.15",
                    release="2.git2d0b8a3.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="a338cf74fe10bce021bbd5d8ba335657",
                    sha1sum=None,
                    sha256sum=
                    "e7c95270d345a04b03d9f2351aca6f2f298764a89bf2039b27de71adc1362f8c",
                ),
                ErratumPackage(
                    arch="SRPMS",
                    filename=
                    "oci-umount-2.3.4-2.git87f9237.module+el8.0.0+2958+4e823551.src.rpm",
                    epoch="2",
                    name="oci-umount",
                    version="2.3.4",
                    release="2.git87f9237.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="aa746cb0a01066d7fa670ca420833cf0",
                    sha1sum=None,
                    sha256sum=
                    "eeb07a3822a3a4e4f78dd94e0e34a3b227d7d17d87ea04267439eb27c2265b33",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "oci-systemd-hook-debuginfo-0.1.15-2.git2d0b8a3.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="1",
                    name="oci-systemd-hook-debuginfo",
                    version="0.1.15",
                    release="2.git2d0b8a3.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="a55e75853de831fec4462adf79257a03",
                    sha1sum=None,
                    sha256sum=
                    "e01939fdfa24a707ed422262bb19a68e5e22995afd0f669be06c33202e00847a",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "oci-systemd-hook-debugsource-0.1.15-2.git2d0b8a3.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="1",
                    name="oci-systemd-hook-debugsource",
                    version="0.1.15",
                    release="2.git2d0b8a3.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="9b29f218aac3861685faff8c69bb03ac",
                    sha1sum=None,
                    sha256sum=
                    "c55dfc5af5c4a715f69b95a3772a4ede50db2d78c88cc9ca00b271d9f8b0c4a4",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "oci-umount-debuginfo-2.3.4-2.git87f9237.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="2",
                    name="oci-umount-debuginfo",
                    version="2.3.4",
                    release="2.git87f9237.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="1f891c443aa35396dd57ae1185f98f9c",
                    sha1sum=None,
                    sha256sum=
                    "344385d9c0cfdca4ddf16876936e36abad91c1cd7b99d3cb86e2fc5f858cb56f",
                ),
                ErratumPackage(
                    arch="s390x",
                    filename=
                    "oci-umount-2.3.4-2.git87f9237.module+el8.0.0+2958+4e823551.s390x.rpm",
                    epoch="2",
                    name="oci-umount",
                    version="2.3.4",
                    release="2.git87f9237.module+el8.0.0+2958+4e823551",
                    src=
                    "container-selinux-2.94-1.git1e99f1d.module+el8.0.0+2958+4e823551.src.rpm",
                    reboot_suggested=None,
                    md5sum="eba982381b3a54d0ae7c14230f29fd69",
                    sha1sum=None,
                    sha256sum=
                    "872610d40f5f50030ef6188d26178ae7b0dc8eedab72e285c8b513f8df145a2b",
                ),
            ],
            short="",
            module=ErratumModule(
                name="container-tools",
                stream="rhel8",
                version="8000020190416221845",
                context="2ffa3d27",
                arch="s390x",
            ),
        ),
    ]

    loaded = attr.evolve(loaded, pkglist=[], references=[])

    assert loaded == ErratumUnit(
        unit_id="d003313d-2272-4ba3-8ea9-820269284dc2",
        id="RHSA-2019:0975",
        version="1",
        status="final",
        updated="2019-05-07 03:39:02 UTC",
        issued="2019-05-07 03:39:11 UTC",
        description=
        "The container-tools module contains tools for working with containers, notably podman, buildah, skopeo, and runc.\n\nSecurity Fix(es):\n\n* A flaw was found in the way runc handled system file descriptors when running containers. A malicious container could use this flaw to overwrite contents of the runc binary and consequently run arbitrary commands on the container host system. (CVE-2019-5736)\n\nFor more details about the security issue(s), including the impact, a CVSS score, acknowledgments, and other related information, refer to the CVE page(s) listed in the References section.\n\nBug Fix(es):\n\n* [stream rhel8] rebase container-selinux to 2.94 (BZ#1693675)\n\n* [stream rhel8] unable to mount disk at `/var/lib/containers` via `systemd` unit when `container-selinux` policy installed (BZ#1695669)\n\n* [stream rhel8] don't allow a container to connect to random services (BZ#1695689)",
        pushcount="8",
        reboot_suggested=False,
        from_="*****@*****.**",
        rights="Copyright 2019 Red Hat Inc",
        title="Important: container-tools:rhel8 security and bug fix update",
        severity="Important",
        release="0",
        type="security",
        solution=
        "For details on how to apply this update, which includes the changes described in this advisory, refer to:\n\nhttps://access.redhat.com/articles/11258",
        summary=
        "An update for the container-tools:rhel8 module is now available for Red Hat Enterprise Linux 8.\n\nRed Hat Product Security has rated this update as having a security impact of Important. A Common Vulnerability Scoring System (CVSS) base score, which gives a detailed severity rating, is available for each vulnerability from the CVE link(s) in the References section.",
        content_types=["module"],
        references=[],
        pkglist=[],
        content_type_id="erratum",
        repository_memberships=[
            "all-rpm-content",
            "rhel-8-for-aarch64-appstream-source-rpms__8_DOT_0",
            "rhel-8-for-aarch64-appstream-source-rpms__8_DOT_1",
            "rhel-8-for-aarch64-appstream-source-rpms__8_DOT_2",
            "rhel-8-for-aarch64-appstream-source-rpms__8_DOT_3",
            "rhel-8-for-ppc64le-appstream-rpms__8_DOT_0",
            "rhel-8-for-ppc64le-appstream-rpms__8_DOT_1",
            "rhel-8-for-ppc64le-appstream-rpms__8_DOT_2",
            "rhel-8-for-ppc64le-appstream-rpms__8_DOT_3",
            "rhel-8-for-s390x-appstream-rpms__8",
            "rhel-8-for-s390x-appstream-rpms__8_DOT_1",
            "rhel-8-for-s390x-appstream-rpms__8_DOT_2",
            "rhel-8-for-x86_64-appstream-rpms__8",
        ],
    )
Beispiel #15
0
def test_upload_erratum(client, requests_mocker):
    """An ErratumUnit can be uploaded to a repository using the client."""

    repo_id = "repo1"
    repo = YumRepository(id=repo_id)
    repo.__dict__["_client"] = client

    unit = ErratumUnit(
        id="RHBA-1234:56",
        summary="A great advisory",
        version="1",
        status="final",
        updated="some updated time",
        issued="some issued time",
        description="testing upload",
        pushcount="507",
        from_="*****@*****.**",
        reboot_suggested=False,
        rights="copyright bob",
        content_types=["rpm", "module"],
        references=[
            ErratumReference(
                title="a link",
                href="https://example.com/test-advisory",
                type="self",
                id="self-id",
            )
        ],
        pkglist=[],
    )

    # Set up the requests it'll do:
    #
    # It will request an upload
    requests_mocker.post(
        "https://pulp.example.com/pulp/api/v2/content/uploads/",
        json={"upload_id": "my-upload-123"},
    )

    # It'll do an import against that upload
    requests_mocker.post(
        "https://pulp.example.com/pulp/api/v2/repositories/repo1/actions/import_upload/",
        json={
            "spawned_tasks": [{
                "task_id": "task123"
            }, {
                "task_id": "task234"
            }]
        },
    )

    # It'll search for status of the import tasks
    requests_mocker.post(
        "https://pulp.example.com/pulp/api/v2/tasks/search/",
        json=[
            {
                "task_id": "task123",
                "state": "finished"
            },
            {
                "task_id": "task234",
                "state": "finished"
            },
        ],
    )

    # It'll clean up the upload
    requests_mocker.delete(
        "https://pulp.example.com/pulp/api/v2/content/uploads/my-upload-123/")

    # Mocker setup is complete.

    # It should start the upload OK
    upload_f = repo.upload_erratum(unit)

    # I can await the result
    tasks = upload_f.result()

    # There should be the two tasks returned from the API
    assert sorted([t.id for t in tasks]) == ["task123", "task234"]

    # Each task should be successful
    for t in tasks:
        assert t.completed
        assert t.succeeded

    # What did the client actually try to import?
    import_request = requests_mocker.request_history[1]

    assert import_request.json() == {
        "upload_id": "my-upload-123",
        "unit_type_id": "erratum",
        "unit_key": {
            "id": "RHBA-1234:56"
        },
        "unit_metadata": {
            # This should contain an accurate serialization of all fields
            # into the form required by Pulp.
            "id":
            "RHBA-1234:56",
            "version":
            "1",
            "status":
            "final",
            "updated":
            "some updated time",
            "issued":
            "some issued time",
            "description":
            "testing upload",
            "pushcount":
            "507",
            "reboot_suggested":
            False,
            "from":
            "*****@*****.**",
            "rights":
            "copyright bob",
            "summary":
            "A great advisory",
            "pulp_user_metadata": {
                "content_types": ["rpm", "module"]
            },
            "references": [{
                "href": "https://example.com/test-advisory",
                "id": "self-id",
                "title": "a link",
                "type": "self",
            }],
            "pkglist": [],
            # Note also that fields not explicitly set will be serialized
            # as None (see doc string on upload_erratum).
            "title":
            None,
            "severity":
            None,
            "release":
            None,
            "type":
            None,
            "solution":
            None,
        },
    }
def test_copy_content_all(controller):
    """copy_content with no criteria copies all units from a repo"""
    src = YumRepository(id="src-repo")
    dest = YumRepository(id="dest-repo")
    other = YumRepository(id="other-repo")
    controller.insert_repository(src)
    controller.insert_repository(dest)
    controller.insert_repository(other)

    # Set up that both 'src' and 'other' contain some units.
    # The units in 'other' are there to ensure that copying only
    # happens from the given source repo and not other repos unexpectedly.
    src_units = [
        ErratumUnit(id="RHSA-1111:22", summary="Fixes bad things"),
        ModulemdUnit(
            name="module1",
            stream="s1",
            version=1234,
            context="a1b2",
            arch="x86_64",
            repository_memberships=["repoA", "repoB"],
        ),
        RpmUnit(
            name="bash",
            version="4.0",
            release="1",
            arch="x86_64",
            # Note: the next two fields aren't part of the unit key on RPM units.
            # We put these here specifically to verify they'll be filtered out
            # on the copy response (as a real Pulp server does).
            filename="bash-4.0-1.x86_64.rpm",
            signing_key="a1b2c3",
        ),
    ]
    controller.insert_units(src, src_units)
    controller.insert_units(
        other,
        [
            RpmUnit(
                name="glibc",
                version="5.0",
                release="1",
                arch="x86_64",
                sourcerpm="glibc-5.0-1.el5_11.1.src.rpm",
            )
        ],
    )

    client = controller.client

    # Repos are initially detached, re-fetch them via client
    src = client.get_repository(src.id).result()
    dest = client.get_repository(dest.id).result()

    # It should succeed
    copy_tasks = list(client.copy_content(src, dest))

    # Gather all units apparently copied
    units = sum([t.units for t in copy_tasks], [])

    # It should copy just the units we expect, from src.
    # Note that these are incomplete views of the units, as (just like real pulp)
    # the fake will only return fields present in the unit_key after a copy.
    assert sorted(units, key=repr) == [
        ErratumUnit(id="RHSA-1111:22"),
        ModulemdUnit(name="module1",
                     stream="s1",
                     version=1234,
                     context="a1b2",
                     arch="x86_64"),
        RpmUnit(name="bash",
                version="4.0",
                release="1",
                arch="x86_64",
                epoch="0"),
    ]

    # The copy should also impact subsequent content searches.
    dest_units = list(dest.search_content())

    # The units we get from the search are not *precisely* the same as src_units,
    # because repository_memberships has been updated.
    assert sorted(dest_units, key=repr) == [
        ErratumUnit(
            unit_id="e3e70682-c209-4cac-629f-6fbed82c07cd",
            id="RHSA-1111:22",
            summary="Fixes bad things",
            content_type_id="erratum",
            repository_memberships=["src-repo", "dest-repo"],
        ),
        ModulemdUnit(
            unit_id="82e2e662-f728-b4fa-4248-5e3a0a5d2f34",
            name="module1",
            stream="s1",
            version=1234,
            context="a1b2",
            arch="x86_64",
            content_type_id="modulemd",
            repository_memberships=["src-repo", "dest-repo", "repoA", "repoB"],
        ),
        RpmUnit(
            unit_id="d4713d60-c8a7-0639-eb11-67b367a9c378",
            name="bash",
            version="4.0",
            release="1",
            arch="x86_64",
            epoch="0",
            signing_key="a1b2c3",
            filename="bash-4.0-1.x86_64.rpm",
            content_type_id="rpm",
            repository_memberships=["src-repo", "dest-repo"],
        ),
    ]
Beispiel #17
0
def test_delete_advisory_no_repos_provided(command_tester, fake_collector,
                                           monkeypatch):
    """Deletion of packages succeeds in all the repos when the same advisory is
    present in multiple repos and repos are not provided in the request"""

    repo1 = YumRepository(id="some-yumrepo",
                          relative_url="some/publish/url",
                          mutable_urls=["repomd.xml"])
    repo2 = YumRepository(
        id="other-yumrepo",
        relative_url="other/publish/url",
        mutable_urls=["repomd.xml"],
    )

    pkglist = [
        ErratumPackageCollection(
            name="collection-1",
            packages=[
                ErratumPackage(
                    name="bash",
                    version="1.23",
                    release="1.test8",
                    arch="x86_64",
                    filename="bash-1.23-1.test8_x86_64.rpm",
                    sha256sum="a" * 64,
                    md5sum="b" * 32,
                ),
                ErratumPackage(
                    name="dash",
                    version="1.23",
                    release="1.test8",
                    arch="x86_64",
                    filename="dash-1.23-1.test8_x86_64.rpm",
                    sha256sum="a" * 64,
                    md5sum="b" * 32,
                ),
            ],
            short="",
            module=None,
        ),
    ]

    files = [
        RpmUnit(
            name="bash",
            version="1.23",
            release="1.test8",
            arch="x86_64",
            filename="bash-1.23-1.test8_x86_64.rpm",
            sha256sum="a" * 64,
            md5sum="b" * 32,
            signing_key="aabbcc",
            unit_id="files1_rpm1",
        ),
        RpmUnit(
            name="dash",
            version="1.23",
            release="1.test8",
            arch="x86_64",
            filename="dash-1.23-1.test8_x86_64.rpm",
            sha256sum="a" * 64,
            md5sum="b" * 32,
            signing_key="aabbcc",
            unit_id="files1_rpm2",
        ),
        RpmUnit(
            name="crash",
            version="1.23",
            release="1.test8",
            arch="x86_64",
            filename=
            "crash-1.23-1.test8.module+el8.0.0+3049+59fd2bba.x86_64.rpm",
            sha256sum="a" * 64,
            md5sum="b" * 32,
            signing_key="aabbcc",
            unit_id="files1_rpm3",
        ),
        ErratumUnit(
            unit_id="x4e73262-e239-44ac-629f-6fbed82c07cd",
            id="RHBA-1001:22",
            summary="Other erratum",
            content_type_id="erratum",
            repository_memberships=["some-yumrepo", "other-yumrepo"],
            pkglist=pkglist,
        ),
    ]

    with FakeDeleteAdvisory() as task_instance:

        task_instance.pulp_client_controller.insert_repository(repo1)
        task_instance.pulp_client_controller.insert_repository(repo2)
        task_instance.pulp_client_controller.insert_units(repo1, files)
        task_instance.pulp_client_controller.insert_units(repo2, files)

        # Let's try setting the cache flush root via env.
        monkeypatch.setenv("FASTPURGE_ROOT_URL", "https://cdn.example2.com/")

        # It should run with expected output.
        command_tester.test(
            task_instance.main,
            [
                "test-delete",
                "--pulp-url",
                "https://pulp.example.com/",
                "--fastpurge-host",
                "fakehost-xxx.example.net",
                "--fastpurge-client-secret",
                "abcdef",
                "--fastpurge-client-token",
                "efg",
                "--fastpurge-access-token",
                "tok",
                "--advisory",
                "RHBA-1001:22",
            ],
        )

        assert sorted(fake_collector.items,
                      key=lambda pi: (pi["filename"], pi["dest"])) == [
                          {
                              "build": None,
                              "checksums": {
                                  "sha256": "a" * 64
                              },
                              "dest": "other-yumrepo",
                              "filename": "bash-1.23-1.test8.x86_64.rpm",
                              "origin": "pulp",
                              "signing_key": None,
                              "src": None,
                              "state": "DELETED",
                          },
                          {
                              "build": None,
                              "checksums": {
                                  "sha256": "a" * 64
                              },
                              "dest": "some-yumrepo",
                              "filename": "bash-1.23-1.test8.x86_64.rpm",
                              "origin": "pulp",
                              "signing_key": None,
                              "src": None,
                              "state": "DELETED",
                          },
                          {
                              "build": None,
                              "checksums": {
                                  "sha256": "a" * 64
                              },
                              "dest": "other-yumrepo",
                              "filename": "dash-1.23-1.test8.x86_64.rpm",
                              "origin": "pulp",
                              "signing_key": None,
                              "src": None,
                              "state": "DELETED",
                          },
                          {
                              "build": None,
                              "checksums": {
                                  "sha256": "a" * 64
                              },
                              "dest": "some-yumrepo",
                              "filename": "dash-1.23-1.test8.x86_64.rpm",
                              "origin": "pulp",
                              "signing_key": None,
                              "src": None,
                              "state": "DELETED",
                          },
                      ]

        # verify whether the rpms were deleted from the repo on Pulp
        client = task_instance.pulp_client

        # get all the repos
        repos = list(
            client.search_repository(
                Criteria.with_id("some-yumrepo")).result())
        assert len(repos) == 1
        repo1 = repos[0]

        repos = list(
            client.search_repository(
                Criteria.with_id("other-yumrepo")).result())
        assert len(repos) == 1
        repo2 = repos[0]

        # list the removed unit's unit_id
        # RPMs from the erratum package list
        unit_ids = ["files1_rpm1", "files1_rpm2"]
        criteria = Criteria.with_field("unit_id", Matcher.in_(unit_ids))

        # deleted packages from the advisory are not in both the repos
        files = list(repo1.search_content(criteria).result())
        assert len(files) == 0

        files = list(repo2.search_content(criteria).result())
        assert len(files) == 0

        # same files exist on Pulp as orphans
        files_search = list(client.search_content(criteria).result())
        assert len(files_search) == 2