mirror of
https://github.com/resf/distro-tools.git
synced 2024-09-12 14:02:37 +00:00
Add apollo_tree and fix pylint warnings
This commit is contained in:
parent
b498d3b889
commit
5e1fde1027
18
.github/workflows/test.yaml
vendored
Normal file
18
.github/workflows/test.yaml
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
name: Lint and test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Lint
|
||||
run: ./build/scripts/pylint.bash
|
||||
- name: Test
|
||||
run: ./build/scripts/test.bash
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -14,5 +14,8 @@
|
||||
"editor.formatOnSave": true,
|
||||
"[python]": {
|
||||
"editor.tabSize": 4
|
||||
},
|
||||
"[xml]": {
|
||||
"editor.formatOnSave": false
|
||||
}
|
||||
}
|
||||
|
346
apollo/publishing_tools/apollo_tree.py
Normal file
346
apollo/publishing_tools/apollo_tree.py
Normal file
@ -0,0 +1,346 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import argparse
|
||||
import asyncio
|
||||
import logging
|
||||
import hashlib
|
||||
import gzip
|
||||
from dataclasses import dataclass
|
||||
import time
|
||||
from urllib.parse import quote
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import aiohttp
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger("apollo_tree")
|
||||
|
||||
NS = {
|
||||
"": "http://linux.duke.edu/metadata/repo",
|
||||
"rpm": "http://linux.duke.edu/metadata/rpm"
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class Repository:
|
||||
base_repomd: str = None
|
||||
source_repomd: str = None
|
||||
debug_repomd: str = None
|
||||
arch: str = None
|
||||
|
||||
|
||||
async def scan_path(
|
||||
base_path: str,
|
||||
fmt: str,
|
||||
ignore_dirs: list[str],
|
||||
):
|
||||
"""
|
||||
Scan base path for repositories
|
||||
The format string can contain $reponame and $arch
|
||||
When we reach $reponame, that means we have found a repository
|
||||
Follow the path further into the tree until $arch is found
|
||||
That determines the architecture of the repository
|
||||
"""
|
||||
|
||||
repos = {}
|
||||
|
||||
# First we need to find the root.
|
||||
# Construct root by prepending base_path and all parts until $reponame
|
||||
# Then we can walk the tree from there
|
||||
root = base_path
|
||||
parts = fmt.split("/")
|
||||
repo_first = True
|
||||
if "$reponame" in parts:
|
||||
for part in parts:
|
||||
parts.pop(0)
|
||||
if part == "$reponame":
|
||||
break
|
||||
if part == "$arch":
|
||||
repo_first = False
|
||||
break
|
||||
root = os.path.join(root, part)
|
||||
|
||||
logger.info("Found root: %s", root)
|
||||
|
||||
# Walk the base path
|
||||
for directory in os.listdir(root):
|
||||
if directory in ignore_dirs:
|
||||
continue
|
||||
current_parts = parts
|
||||
if repo_first:
|
||||
repo_name = directory
|
||||
logger.info("Found repo: %s", repo_name)
|
||||
else:
|
||||
arch = directory
|
||||
logger.info("Found arch: %s", arch)
|
||||
repo_base = os.path.join(root, directory)
|
||||
|
||||
if repo_first:
|
||||
repos[repo_name] = []
|
||||
|
||||
# Construct repo base until we reach $arch
|
||||
if "$arch" in current_parts:
|
||||
for part in current_parts:
|
||||
if (part == "$arch" and repo_first) or part == "$reponame":
|
||||
break
|
||||
repo_base = os.path.join(repo_base, part)
|
||||
current_parts.pop(0)
|
||||
|
||||
logger.warning("Searching for arches in %s", repo_base)
|
||||
|
||||
# All dirs in repo_base is an architecture
|
||||
for arch_ in os.listdir(repo_base):
|
||||
if repo_first:
|
||||
arch = arch_
|
||||
else:
|
||||
repo_name = arch_
|
||||
# Now append each combination + rest of parts as repo_info
|
||||
if repo_first:
|
||||
logger.info("Found arch: %s", arch)
|
||||
else:
|
||||
logger.info("Found repo: %s", repo_name)
|
||||
|
||||
if repo_first:
|
||||
found_path = f"{repo_base}/{arch}/{'/'.join(current_parts[1:])}"
|
||||
else:
|
||||
found_path = f"{repo_base}/{repo_name}/{'/'.join(current_parts[1:])}"
|
||||
|
||||
# Verify that the path exists
|
||||
if not os.path.exists(found_path):
|
||||
logger.warning("Path does not exist: %s, skipping", found_path)
|
||||
continue
|
||||
|
||||
repo = {
|
||||
"name": repo_name,
|
||||
"arch": arch,
|
||||
"found_path": found_path,
|
||||
}
|
||||
if repo_name not in repos:
|
||||
repos[repo_name] = []
|
||||
repos[repo_name].append(repo)
|
||||
|
||||
return repos
|
||||
|
||||
|
||||
async def fetch_updateinfo_from_apollo(
|
||||
repo: dict,
|
||||
product_name: str,
|
||||
arch: str = None,
|
||||
api_base: str = None,
|
||||
) -> str:
|
||||
if not api_base:
|
||||
api_base = "https://apollo.build.resf.org/api/v3/updateinfo"
|
||||
api_url = f"{api_base}/{quote(product_name)}/{quote(repo['name'])}/updateinfo.xml"
|
||||
if arch:
|
||||
api_url += f"?req_arch={arch}"
|
||||
|
||||
logger.info("Fetching updateinfo from %s", api_url)
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(api_url) as resp:
|
||||
if resp.status != 200:
|
||||
logger.error("Failed to fetch updateinfo from %s", api_url)
|
||||
return None
|
||||
return await resp.text()
|
||||
|
||||
|
||||
async def gzip_updateinfo(updateinfo: str) -> dict:
|
||||
# Gzip updateinfo, get both open and closed size as
|
||||
# well as the sha256sum for both
|
||||
|
||||
# First get the sha256sum and size of the open updateinfo
|
||||
sha256sum = hashlib.sha256(updateinfo.encode("utf-8")).hexdigest()
|
||||
size = len(updateinfo)
|
||||
|
||||
# Then gzip it and get hash and size
|
||||
gzipped = gzip.compress(updateinfo.encode("utf-8"), mtime=0)
|
||||
gzipped_sha256sum = hashlib.sha256(gzipped).hexdigest()
|
||||
gzipped_size = len(gzipped)
|
||||
|
||||
return {
|
||||
"sha256sum": sha256sum,
|
||||
"size": size,
|
||||
"gzipped_sha256sum": gzipped_sha256sum,
|
||||
"gzipped_size": gzipped_size,
|
||||
"gzipped": gzipped,
|
||||
}
|
||||
|
||||
|
||||
async def write_updateinfo_to_file(
|
||||
repomd_xml_path: str, updateinfo: dict
|
||||
) -> str:
|
||||
# Write updateinfo to file
|
||||
repomd_dir = os.path.dirname(repomd_xml_path)
|
||||
gzipped_sum = updateinfo["gzipped_sha256sum"]
|
||||
updateinfo_path = os.path.join(
|
||||
repomd_dir, f"{gzipped_sum}-updateinfo.xml.gz"
|
||||
)
|
||||
with open(updateinfo_path, "wb") as f:
|
||||
f.write(updateinfo["gzipped"])
|
||||
|
||||
return updateinfo_path
|
||||
|
||||
|
||||
async def update_repomd_xml(repomd_xml_path: str, updateinfo: dict):
|
||||
# Update repomd.xml with new updateinfo
|
||||
gzipped_sum = updateinfo["gzipped_sha256sum"]
|
||||
updateinfo_path = f"{gzipped_sum}-updateinfo.xml.gz"
|
||||
|
||||
# Parse repomd.xml
|
||||
ET.register_namespace("", NS[""])
|
||||
ET.register_namespace("rpm", NS["rpm"])
|
||||
repomd_xml = ET.parse(repomd_xml_path).getroot()
|
||||
|
||||
# Iterate over data and find type="updateinfo" and delete it
|
||||
existing_updateinfo_path = None
|
||||
for data in repomd_xml.findall("data", NS):
|
||||
data_type = data.attrib["type"]
|
||||
if not data_type:
|
||||
logger.warning("No type found in data, skipping")
|
||||
continue
|
||||
if data_type == "updateinfo":
|
||||
# Delete the data element
|
||||
repomd_xml.remove(data)
|
||||
|
||||
# Get the location of the updateinfo file
|
||||
location = data.find("location", NS)
|
||||
if not location:
|
||||
logger.warning("No location found in data, skipping")
|
||||
continue
|
||||
existing_updateinfo_path = location.attrib["href"]
|
||||
break
|
||||
|
||||
# Create new data element and set type to updateinfo
|
||||
data = ET.Element("data")
|
||||
data.set("type", "updateinfo")
|
||||
|
||||
# Add checksum, open-checksum, location, timestamp, size and open-size
|
||||
checksum = ET.SubElement(data, "checksum")
|
||||
checksum.set("type", "sha256")
|
||||
checksum.text = updateinfo["gzipped_sha256sum"]
|
||||
|
||||
open_checksum = ET.SubElement(data, "open-checksum")
|
||||
open_checksum.set("type", "sha256")
|
||||
open_checksum.text = updateinfo["sha256sum"]
|
||||
|
||||
location = ET.SubElement(data, "location")
|
||||
location.set("href", f"repodata/{updateinfo_path}")
|
||||
|
||||
timestamp = ET.SubElement(data, "timestamp")
|
||||
timestamp.text = str(int(time.time()))
|
||||
|
||||
size = ET.SubElement(data, "size")
|
||||
size.text = str(updateinfo["gzipped_size"])
|
||||
|
||||
open_size = ET.SubElement(data, "open-size")
|
||||
open_size.text = str(updateinfo["size"])
|
||||
|
||||
# Add data to repomd.xml
|
||||
repomd_xml.append(data)
|
||||
|
||||
# Create string
|
||||
ET.indent(repomd_xml)
|
||||
xml_str = ET.tostring(
|
||||
repomd_xml,
|
||||
xml_declaration=True,
|
||||
encoding="utf-8",
|
||||
short_empty_elements=True,
|
||||
)
|
||||
|
||||
# Prepend declaration with double quotes
|
||||
xml_str = xml_str.decode("utf-8")
|
||||
xml_str = xml_str.replace("'", "\"")
|
||||
xml_str = xml_str.replace("utf-8", "UTF-8")
|
||||
|
||||
# "Fix" closing tags to not have a space
|
||||
xml_str = xml_str.replace(" />", "/>")
|
||||
|
||||
# Add xmlns:rpm
|
||||
xml_str = xml_str.replace(
|
||||
"repo\">",
|
||||
f"repo\" xmlns:rpm=\"{NS['rpm']}\">",
|
||||
)
|
||||
|
||||
# Write to repomd.xml
|
||||
with open(repomd_xml_path, "w", encoding="utf-8") as f:
|
||||
f.write(xml_str)
|
||||
|
||||
# Delete old updateinfo file
|
||||
if existing_updateinfo_path:
|
||||
os.remove(existing_updateinfo_path)
|
||||
|
||||
|
||||
async def main(args):
|
||||
base_paths = await scan_path(
|
||||
args.path,
|
||||
args.base_format,
|
||||
args.ignore,
|
||||
)
|
||||
print(args)
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="apollo_tree",
|
||||
description="Apollo updateinfo.xml publisher (Local file tree)",
|
||||
epilog="(C) 2023 Rocky Enterprise Software Foundation, Inc.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-b",
|
||||
"--base-format",
|
||||
default="$reponame/$arch/os/repodata/repomd.xml",
|
||||
help="Format for main repo.xml file",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-m",
|
||||
"--manual",
|
||||
action="store_true",
|
||||
help="Manual mode",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--repos",
|
||||
nargs="+",
|
||||
action="append",
|
||||
default=[],
|
||||
help="Repositories to publish (manual mode), format: <arch>:<repomd>",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
"--auto-scan",
|
||||
default=True,
|
||||
action="store_true",
|
||||
help="Automatically scan for repos",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--path",
|
||||
help="Default path to scan for repos",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-i",
|
||||
"--ignore",
|
||||
nargs="+",
|
||||
action="append",
|
||||
default=[],
|
||||
help="Directories in base path to ignore in auto-scan mode",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--product-name",
|
||||
required=True,
|
||||
help="Product name",
|
||||
)
|
||||
|
||||
p_args = parser.parse_args()
|
||||
if p_args.auto_scan and p_args.manual:
|
||||
parser.error("Cannot use --auto-scan and --manual together")
|
||||
|
||||
if p_args.manual and not p_args.repos:
|
||||
parser.error("Must specify repos to publish in manual mode")
|
||||
|
||||
if p_args.auto_scan and not p_args.path:
|
||||
parser.error("Must specify path to scan for repos in auto-scan mode")
|
||||
|
||||
asyncio.run(main(p_args))
|
@ -126,7 +126,11 @@ class Advisory(JSONWizard):
|
||||
Returns whether this advisory affects the given RHEL version and architecture.
|
||||
"""
|
||||
for product in self.get_products():
|
||||
if product.variant == "Red Hat Enterprise Linux" and product.major_version == major_version and product.minor_version == minor_version and product.arch == arch.value:
|
||||
is_variant = product.variant == "Red Hat Enterprise Linux"
|
||||
is_major_version = product.major_version == major_version
|
||||
is_minor_version = product.minor_version == minor_version
|
||||
is_arch = product.arch == arch.value
|
||||
if is_variant and is_major_version and is_minor_version and is_arch:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
@ -1,5 +1,4 @@
|
||||
import asyncio
|
||||
import datetime
|
||||
from __init__ import API, Architecture
|
||||
|
||||
|
||||
|
@ -8,8 +8,6 @@ from os import path
|
||||
import aiohttp
|
||||
import yaml
|
||||
|
||||
from common.logger import Logger
|
||||
|
||||
NVRA_RE = re.compile(
|
||||
r"^(\S+)-([\w~%.+]+)-(\w+(?:\.[\w~%+]+)+?)(?:\.(\w+))?(?:\.rpm)?$"
|
||||
)
|
||||
|
@ -111,7 +111,7 @@ async def clone_advisory(
|
||||
logger = Logger()
|
||||
logger.info("Cloning advisory %s to %s", advisory.name, product.name)
|
||||
|
||||
acceptable_arches = list(set([x.match_arch for x in mirrors]))
|
||||
acceptable_arches = list({x.match_arch for x in mirrors})
|
||||
acceptable_arches.extend(["src", "noarch"])
|
||||
for mirror in mirrors:
|
||||
if mirror.match_arch == "x86_64":
|
||||
@ -377,14 +377,12 @@ async def clone_advisory(
|
||||
|
||||
# Check if topic is empty, if so construct it
|
||||
if not new_advisory.topic:
|
||||
package_names = list(set([p.package_name for p in new_pkgs]))
|
||||
package_names = list({p.package_name for p in new_pkgs})
|
||||
affected_products = list(
|
||||
set(
|
||||
[
|
||||
f"{product.name} {mirror.match_major_version}"
|
||||
for mirror in mirrors
|
||||
]
|
||||
)
|
||||
{
|
||||
f"{product.name} {mirror.match_major_version}"
|
||||
for mirror in mirrors
|
||||
}
|
||||
)
|
||||
topic = f"""An update is available for {', '.join(package_names)}.
|
||||
This update affects {', '.join(affected_products)}.
|
||||
|
@ -125,4 +125,4 @@ async def get_advisory(request: Request, advisory_name: str):
|
||||
"advisory": advisory,
|
||||
"package_map": package_map,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
@ -1,6 +1,6 @@
|
||||
from typing import TypeVar, Generic
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi import APIRouter
|
||||
from fastapi.exceptions import HTTPException
|
||||
from fastapi_pagination.links import Page
|
||||
from fastapi_pagination.ext.tortoise import paginate
|
||||
|
@ -90,12 +90,10 @@ def v3_advisory_to_v2(
|
||||
kind = "TYPE_ENHANCEMENT"
|
||||
|
||||
affected_products = list(
|
||||
set(
|
||||
[
|
||||
f"{ap.variant} {ap.major_version}"
|
||||
for ap in advisory.affected_products
|
||||
]
|
||||
)
|
||||
{
|
||||
f"{ap.variant} {ap.major_version}"
|
||||
for ap in advisory.affected_products
|
||||
}
|
||||
)
|
||||
|
||||
cves = []
|
||||
|
@ -67,7 +67,7 @@ async def health():
|
||||
|
||||
|
||||
@app.exception_handler(404)
|
||||
async def not_found_handler(request, exc):
|
||||
async def not_found_handler(request, exc): # pylint: disable=unused-argument
|
||||
if request.url.path.startswith("/api"
|
||||
) or request.url.path.startswith("/v2"):
|
||||
return JSONResponse({"error": "Not found"}, status_code=404)
|
||||
|
0
apollo/tests/BUILD.bazel
Normal file
0
apollo/tests/BUILD.bazel
Normal file
0
apollo/tests/publishing_tools/BUILD.bazel
Normal file
0
apollo/tests/publishing_tools/BUILD.bazel
Normal file
@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<repomd xmlns="http://linux.duke.edu/metadata/repo" xmlns:rpm="http://linux.duke.edu/metadata/rpm">
|
||||
<revision>8.7</revision>
|
||||
<tags>
|
||||
<distro cpeid="cpe:/o:rocky:rocky:8">Rocky Linux 8</distro>
|
||||
</tags>
|
||||
<data type="primary">
|
||||
<checksum type="sha256">602602cc03961da7245740aa32af042c28fa7a4bed01e9f51dcde8326c6240e3</checksum>
|
||||
<open-checksum type="sha256">a69fcb753072006097c806f9f441553e5086b1369180a72ae719fad654246554</open-checksum>
|
||||
<location href="repodata/602602cc03961da7245740aa32af042c28fa7a4bed01e9f51dcde8326c6240e3-primary.xml.gz"/>
|
||||
<timestamp>1674782842</timestamp>
|
||||
<size>1648129</size>
|
||||
<open-size>16701409</open-size>
|
||||
</data>
|
||||
<data type="filelists">
|
||||
<checksum type="sha256">693e2deed8288074851942f71f525bfce865a71734214fa434010dd00a215283</checksum>
|
||||
<open-checksum type="sha256">bc311897f94631363f555ef354525f28613df9effb7e4a0459acffea29bf3ba1</open-checksum>
|
||||
<location href="repodata/693e2deed8288074851942f71f525bfce865a71734214fa434010dd00a215283-filelists.xml.gz"/>
|
||||
<timestamp>1674782842</timestamp>
|
||||
<size>6162410</size>
|
||||
<open-size>87526801</open-size>
|
||||
</data>
|
||||
<data type="other">
|
||||
<checksum type="sha256">fd97455be05a44ffe98685a63031d1ac10661ca0c0bafa747dfae6c479261e6d</checksum>
|
||||
<open-checksum type="sha256">518c3a001a453adb34cf5a70ceecf11aa2d90f0c807c879d76a02f7123f5c22f</open-checksum>
|
||||
<location href="repodata/fd97455be05a44ffe98685a63031d1ac10661ca0c0bafa747dfae6c479261e6d-other.xml.gz"/>
|
||||
<timestamp>1674782842</timestamp>
|
||||
<size>1102970</size>
|
||||
<open-size>12298845</open-size>
|
||||
</data>
|
||||
<data type="primary_db">
|
||||
<checksum type="sha256">ae73143161fda8b62f6b1cc333ee3fcd4100daa0947a5b918e80b4a487ded360</checksum>
|
||||
<open-checksum type="sha256">9f9b5bb6f1772f3f742f66245041246021777015d1d30970d5410b988cdd233a</open-checksum>
|
||||
<location href="repodata/ae73143161fda8b62f6b1cc333ee3fcd4100daa0947a5b918e80b4a487ded360-primary.sqlite.xz"/>
|
||||
<timestamp>1674782850</timestamp>
|
||||
<size>2724240</size>
|
||||
<open-size>17735680</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="filelists_db">
|
||||
<checksum type="sha256">75d9455e941cb3e8a5266980b78eccb26476198bb4a1f3142ee6cda05ed044f9</checksum>
|
||||
<open-checksum type="sha256">23c2249ccb4fe69474b41c1399aac94d4fd1a1d2c6c2cefc46cb23d4dd52e3b0</open-checksum>
|
||||
<location href="repodata/75d9455e941cb3e8a5266980b78eccb26476198bb4a1f3142ee6cda05ed044f9-filelists.sqlite.xz"/>
|
||||
<timestamp>1674782854</timestamp>
|
||||
<size>4556600</size>
|
||||
<open-size>37732352</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="other_db">
|
||||
<checksum type="sha256">f3968e32961df9482a5c265adaeae9a3435c03b81b2c76cfd7c8b1a74337b972</checksum>
|
||||
<open-checksum type="sha256">e84a16aa1bec1a0d6af28ced81aa3a0708d2599b56abbedb858caced501576e9</open-checksum>
|
||||
<location href="repodata/f3968e32961df9482a5c265adaeae9a3435c03b81b2c76cfd7c8b1a74337b972-other.sqlite.xz"/>
|
||||
<timestamp>1674782846</timestamp>
|
||||
<size>1113696</size>
|
||||
<open-size>10711040</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="group">
|
||||
<checksum type="sha256">341f7a33a85d237227c4b814e5ffd57cc7ead34dab6ca79db4feff8520803b22</checksum>
|
||||
<location href="repodata/341f7a33a85d237227c4b814e5ffd57cc7ead34dab6ca79db4feff8520803b22-comps-AppStream.aarch64.xml"/>
|
||||
<timestamp>1674782725</timestamp>
|
||||
<size>428231</size>
|
||||
</data>
|
||||
<data type="group_xz">
|
||||
<checksum type="sha256">c0562df3ad4d3d47bb8076482351eca478a02f4bd15e21b4683456268920154a</checksum>
|
||||
<open-checksum type="sha256">341f7a33a85d237227c4b814e5ffd57cc7ead34dab6ca79db4feff8520803b22</open-checksum>
|
||||
<location href="repodata/c0562df3ad4d3d47bb8076482351eca478a02f4bd15e21b4683456268920154a-comps-AppStream.aarch64.xml.xz"/>
|
||||
<timestamp>1674782842</timestamp>
|
||||
<size>73836</size>
|
||||
<open-size>428231</open-size>
|
||||
</data>
|
||||
<data type="modules">
|
||||
<checksum type="sha256">d53d510b653b6356691a5e9cf5adf2f803c525f0c9f908adf9ccbb6c88a13967</checksum>
|
||||
<open-checksum type="sha256">479622387203132ad97518c6ccdf2a41996f2fddc8a5c9bdf09fcb7407064c09</open-checksum>
|
||||
<location href="repodata/d53d510b653b6356691a5e9cf5adf2f803c525f0c9f908adf9ccbb6c88a13967-modules.yaml.xz"/>
|
||||
<timestamp>1674783016</timestamp>
|
||||
<size>73124</size>
|
||||
<open-size>712620</open-size>
|
||||
</data>
|
||||
<data type="updateinfo">
|
||||
<checksum type="sha256">be8915c2f7ed08fca20532364bd01b12ab51e826d45233f92832f318d1b78c3e</checksum>
|
||||
<open-checksum type="sha256">eec1c28a088aea1719b3ef2edacba8cdc78658fcf65009d2520f76e43ba90566</open-checksum>
|
||||
<location href="repodata/be8915c2f7ed08fca20532364bd01b12ab51e826d45233f92832f318d1b78c3e-updateinfo.xml.gz"/>
|
||||
<timestamp>1674284973</timestamp>
|
||||
<size>233607</size>
|
||||
<open-size>2402781</open-size>
|
||||
</data>
|
||||
</repomd>
|
@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<repomd xmlns="http://linux.duke.edu/metadata/repo" xmlns:rpm="http://linux.duke.edu/metadata/rpm">
|
||||
<revision>8.7</revision>
|
||||
<tags>
|
||||
<distro cpeid="cpe:/o:rocky:rocky:8">Rocky Linux 8</distro>
|
||||
</tags>
|
||||
<data type="primary">
|
||||
<checksum type="sha256">593ce13bf52aadd58d9da7c2b3fc2149bffd7bc4924c7032946b51cc340fc976</checksum>
|
||||
<open-checksum type="sha256">c808007edc3392c44ac219825b4c73f4ba717721f4df2dc9aba023413d3dfab0</open-checksum>
|
||||
<location href="repodata/593ce13bf52aadd58d9da7c2b3fc2149bffd7bc4924c7032946b51cc340fc976-primary.xml.gz"/>
|
||||
<timestamp>1674781924</timestamp>
|
||||
<size>1962142</size>
|
||||
<open-size>20488457</open-size>
|
||||
</data>
|
||||
<data type="filelists">
|
||||
<checksum type="sha256">bce97b0287c0f9f9d900b5c9681cfe73f69890c26aae9792fffe25429fc2186b</checksum>
|
||||
<open-checksum type="sha256">4e7729a83d7917070277bc630cc8cea6a620fab59d584a12dc7252d33e8c5632</open-checksum>
|
||||
<location href="repodata/bce97b0287c0f9f9d900b5c9681cfe73f69890c26aae9792fffe25429fc2186b-filelists.xml.gz"/>
|
||||
<timestamp>1674781924</timestamp>
|
||||
<size>7066338</size>
|
||||
<open-size>99500723</open-size>
|
||||
</data>
|
||||
<data type="other">
|
||||
<checksum type="sha256">902ea6dea89caac9980c8599cd53ce154a1e8bff3a1d212d70c38d823e08c028</checksum>
|
||||
<open-checksum type="sha256">c5f4414a2cacff80f6c038761e440f61ed4c6bdefeba66e0062f228be408afc9</open-checksum>
|
||||
<location href="repodata/902ea6dea89caac9980c8599cd53ce154a1e8bff3a1d212d70c38d823e08c028-other.xml.gz"/>
|
||||
<timestamp>1674781924</timestamp>
|
||||
<size>1263392</size>
|
||||
<open-size>15731326</open-size>
|
||||
</data>
|
||||
<data type="primary_db">
|
||||
<checksum type="sha256">c1b32bc2fcef5863e3d0ab03263dbee5d645eb5b299d76a6edf23701504544a3</checksum>
|
||||
<open-checksum type="sha256">ef04c60effc3269b15aa41d99713169e1fa0ea9196ce5167c6096d42e9ae8c0a</open-checksum>
|
||||
<location href="repodata/c1b32bc2fcef5863e3d0ab03263dbee5d645eb5b299d76a6edf23701504544a3-primary.sqlite.xz"/>
|
||||
<timestamp>1674781934</timestamp>
|
||||
<size>3321344</size>
|
||||
<open-size>21495808</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="filelists_db">
|
||||
<checksum type="sha256">bcf3f665052787a1f84ce5de17cc05ab0aa526de282ef6dfcdd8c8a75bf2ac26</checksum>
|
||||
<open-checksum type="sha256">8bd4fd292c8b4041acfc0a113f8e457b55bc2ad75755e17c70e116d71f6b6019</open-checksum>
|
||||
<location href="repodata/bcf3f665052787a1f84ce5de17cc05ab0aa526de282ef6dfcdd8c8a75bf2ac26-filelists.sqlite.xz"/>
|
||||
<timestamp>1674781938</timestamp>
|
||||
<size>5256956</size>
|
||||
<open-size>44195840</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="other_db">
|
||||
<checksum type="sha256">5c1e7e3286c934c684bbe451356d9ac31968f4e786faa209f0bb3080fe02d67f</checksum>
|
||||
<open-checksum type="sha256">88246653b636218807ef6f1174590614851df489be10ae8e462bd38e21c6ef2b</open-checksum>
|
||||
<location href="repodata/5c1e7e3286c934c684bbe451356d9ac31968f4e786faa209f0bb3080fe02d67f-other.sqlite.xz"/>
|
||||
<timestamp>1674781929</timestamp>
|
||||
<size>1385640</size>
|
||||
<open-size>13701120</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="group">
|
||||
<checksum type="sha256">ec2fa1982439f4b0ca7dc86f882f18657457a2d42f06ac6718298c7f7528df43</checksum>
|
||||
<location href="repodata/ec2fa1982439f4b0ca7dc86f882f18657457a2d42f06ac6718298c7f7528df43-comps-AppStream.x86_64.xml"/>
|
||||
<timestamp>1674781761</timestamp>
|
||||
<size>486316</size>
|
||||
</data>
|
||||
<data type="group_xz">
|
||||
<checksum type="sha256">7ba43f88671d8107d6603ebff822fc071e73596a1e20779855af577b0e6e343a</checksum>
|
||||
<open-checksum type="sha256">ec2fa1982439f4b0ca7dc86f882f18657457a2d42f06ac6718298c7f7528df43</open-checksum>
|
||||
<location href="repodata/7ba43f88671d8107d6603ebff822fc071e73596a1e20779855af577b0e6e343a-comps-AppStream.x86_64.xml.xz"/>
|
||||
<timestamp>1674781925</timestamp>
|
||||
<size>81840</size>
|
||||
<open-size>486316</open-size>
|
||||
</data>
|
||||
<data type="modules">
|
||||
<checksum type="sha256">7facfc73e398abc34445310a258754aae5ea0add698c4ea039580a43897d0d02</checksum>
|
||||
<open-checksum type="sha256">da557db5bfd41e8949f8c3904f963cd81fcc444aa4fcc9e99a47ed843948140b</open-checksum>
|
||||
<location href="repodata/7facfc73e398abc34445310a258754aae5ea0add698c4ea039580a43897d0d02-modules.yaml.xz"/>
|
||||
<timestamp>1674782139</timestamp>
|
||||
<size>76500</size>
|
||||
<open-size>742747</open-size>
|
||||
</data>
|
||||
<data type="updateinfo">
|
||||
<checksum type="sha256">5c45121e44d7b58060fb9435733d3ac4e03f2e1965cacd5371eb1649e15d5c06</checksum>
|
||||
<open-checksum type="sha256">dda8db3b243e33262f799fb4361bd21a16b1ff22ddd0224bd18070496942cf3d</open-checksum>
|
||||
<location href="repodata/5c45121e44d7b58060fb9435733d3ac4e03f2e1965cacd5371eb1649e15d5c06-updateinfo.xml.gz"/>
|
||||
<timestamp>1674284975</timestamp>
|
||||
<size>276699</size>
|
||||
<open-size>2720880</open-size>
|
||||
</data>
|
||||
</repomd>
|
@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<repomd xmlns="http://linux.duke.edu/metadata/repo" xmlns:rpm="http://linux.duke.edu/metadata/rpm">
|
||||
<revision>8.7</revision>
|
||||
<tags>
|
||||
<distro cpeid="cpe:/o:rocky:rocky:8">Rocky Linux 8</distro>
|
||||
</tags>
|
||||
<data type="primary">
|
||||
<checksum type="sha256">9f55c0c1cf7cb1fe08bc208f0286d64f274339df4ba857ba978e544a9924fa92</checksum>
|
||||
<open-checksum type="sha256">8a5e972376710cb07fc5eb1f559d0c4456b1b58a36d219474eae66b4d10f7040</open-checksum>
|
||||
<location href="repodata/9f55c0c1cf7cb1fe08bc208f0286d64f274339df4ba857ba978e544a9924fa92-primary.xml.gz"/>
|
||||
<timestamp>1674782716</timestamp>
|
||||
<size>1346598</size>
|
||||
<open-size>9900543</open-size>
|
||||
</data>
|
||||
<data type="filelists">
|
||||
<checksum type="sha256">0457005390605cd3154a88584c7ef6a0e5e37a15c8035dfcde72f9d832ab14e2</checksum>
|
||||
<open-checksum type="sha256">ae8651d8f568994088e3fc576538c6f4638ec29475d6d4c4739fd492028fc0fb</open-checksum>
|
||||
<location href="repodata/0457005390605cd3154a88584c7ef6a0e5e37a15c8035dfcde72f9d832ab14e2-filelists.xml.gz"/>
|
||||
<timestamp>1674782716</timestamp>
|
||||
<size>1523844</size>
|
||||
<open-size>19386269</open-size>
|
||||
</data>
|
||||
<data type="other">
|
||||
<checksum type="sha256">30399987025d0024ccf2d1ee6e1b412361d547cc50813777e42730375a3925dd</checksum>
|
||||
<open-checksum type="sha256">8ea81e1b6d4333cc8553fc4ddd95dc3119e763e7a0c81ea753531fb8f4d7d56a</open-checksum>
|
||||
<location href="repodata/30399987025d0024ccf2d1ee6e1b412361d547cc50813777e42730375a3925dd-other.xml.gz"/>
|
||||
<timestamp>1674782716</timestamp>
|
||||
<size>829148</size>
|
||||
<open-size>5197359</open-size>
|
||||
</data>
|
||||
<data type="primary_db">
|
||||
<checksum type="sha256">5e78af661835050ef33470ed4c00b81ed2e9f8a76629fc7b8f04153ae273eaca</checksum>
|
||||
<open-checksum type="sha256">ced2ee6fd2db2e01b5ba521a2a7815c6ab84c1b1cc95dd41acf55faf90f819c6</open-checksum>
|
||||
<location href="repodata/5e78af661835050ef33470ed4c00b81ed2e9f8a76629fc7b8f04153ae273eaca-primary.sqlite.xz"/>
|
||||
<timestamp>1674782721</timestamp>
|
||||
<size>1663124</size>
|
||||
<open-size>10960896</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="filelists_db">
|
||||
<checksum type="sha256">513e605dd419c53c13f1aa3688ca53338e149dbe6de19b9c8453102bcb9ce882</checksum>
|
||||
<open-checksum type="sha256">3639a0d1ea827449d47564f4330fe8426d37c1cf96308ed13d40fb3460036104</open-checksum>
|
||||
<location href="repodata/513e605dd419c53c13f1aa3688ca53338e149dbe6de19b9c8453102bcb9ce882-filelists.sqlite.xz"/>
|
||||
<timestamp>1674782720</timestamp>
|
||||
<size>1412020</size>
|
||||
<open-size>10305536</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="other_db">
|
||||
<checksum type="sha256">33bddcd2c405ef925318e88662acd38f3a7246e78ebaf88639fe7c43c215095e</checksum>
|
||||
<open-checksum type="sha256">b8d0ffdf150621ecc96e0aa587a895f765e0401937b50ff98e5f2312e3965774</open-checksum>
|
||||
<location href="repodata/33bddcd2c405ef925318e88662acd38f3a7246e78ebaf88639fe7c43c215095e-other.sqlite.xz"/>
|
||||
<timestamp>1674782717</timestamp>
|
||||
<size>356456</size>
|
||||
<open-size>5017600</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="group">
|
||||
<checksum type="sha256">5f2dec3cbb871be9fb6c456740458773b183987275a1d5c93920d4800323fdf9</checksum>
|
||||
<location href="repodata/5f2dec3cbb871be9fb6c456740458773b183987275a1d5c93920d4800323fdf9-comps-BaseOS.aarch64.xml"/>
|
||||
<timestamp>1674782695</timestamp>
|
||||
<size>289214</size>
|
||||
</data>
|
||||
<data type="group_xz">
|
||||
<checksum type="sha256">01f25f36dcb08b5b027ce222dec48e68bcaa6b9e96de863ce60f126897f76faf</checksum>
|
||||
<open-checksum type="sha256">5f2dec3cbb871be9fb6c456740458773b183987275a1d5c93920d4800323fdf9</open-checksum>
|
||||
<location href="repodata/01f25f36dcb08b5b027ce222dec48e68bcaa6b9e96de863ce60f126897f76faf-comps-BaseOS.aarch64.xml.xz"/>
|
||||
<timestamp>1674782716</timestamp>
|
||||
<size>55624</size>
|
||||
<open-size>289214</open-size>
|
||||
</data>
|
||||
<data type="updateinfo">
|
||||
<checksum type="sha256">cb9bb3ef856440c44a70f4f0aa9ee1b3621814c3457f922cdb02d7ed63a2701f</checksum>
|
||||
<open-checksum type="sha256">596fc124c74802371ff879a1ecc3a7560704413bbfb4a5ab9299671baf12c2fb</open-checksum>
|
||||
<location href="repodata/cb9bb3ef856440c44a70f4f0aa9ee1b3621814c3457f922cdb02d7ed63a2701f-updateinfo.xml.gz"/>
|
||||
<timestamp>1674284975</timestamp>
|
||||
<size>45141</size>
|
||||
<open-size>433034</open-size>
|
||||
</data>
|
||||
</repomd>
|
@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<repomd xmlns="http://linux.duke.edu/metadata/repo" xmlns:rpm="http://linux.duke.edu/metadata/rpm">
|
||||
<revision>8.7</revision>
|
||||
<tags>
|
||||
<distro cpeid="cpe:/o:rocky:rocky:8">Rocky Linux 8</distro>
|
||||
</tags>
|
||||
<data type="primary">
|
||||
<checksum type="sha256">712e4af06a8f9f13766274c3fa83bbdf5572a1014ec77f7cd30d56d492a40db2</checksum>
|
||||
<open-checksum type="sha256">c3ec31964ce06e7dc14a8184ad11d6f1edce3a718bd63e4de8ed18349d27e85e</open-checksum>
|
||||
<location href="repodata/712e4af06a8f9f13766274c3fa83bbdf5572a1014ec77f7cd30d56d492a40db2-primary.xml.gz"/>
|
||||
<timestamp>1674781748</timestamp>
|
||||
<size>1791032</size>
|
||||
<open-size>13677600</open-size>
|
||||
</data>
|
||||
<data type="filelists">
|
||||
<checksum type="sha256">052aea22e07e586ae9383f6da4056599417fc445431c9d0b1136f0316ef4843e</checksum>
|
||||
<open-checksum type="sha256">dd5952122ed4335b799b1853f096f05b9e9ea6ea1a48e344700b7b82f468d61f</open-checksum>
|
||||
<location href="repodata/052aea22e07e586ae9383f6da4056599417fc445431c9d0b1136f0316ef4843e-filelists.xml.gz"/>
|
||||
<timestamp>1674781749</timestamp>
|
||||
<size>1800846</size>
|
||||
<open-size>22806093</open-size>
|
||||
</data>
|
||||
<data type="other">
|
||||
<checksum type="sha256">37421cd13a9594ff7dd3a0f2953aa19a01290e90be43db4ce279fef4394fdcd0</checksum>
|
||||
<open-checksum type="sha256">3be8a12fb7bcd600b178f6b00404d1e4e9196b9f0d5faea460c58b8d07771747</open-checksum>
|
||||
<location href="repodata/37421cd13a9594ff7dd3a0f2953aa19a01290e90be43db4ce279fef4394fdcd0-other.xml.gz"/>
|
||||
<timestamp>1674781749</timestamp>
|
||||
<size>878178</size>
|
||||
<open-size>6343206</open-size>
|
||||
</data>
|
||||
<data type="primary_db">
|
||||
<checksum type="sha256">2b1d2886dec67d493adcf7358e44b7f7fd4886c85bab7fa9854014ad9c404d7a</checksum>
|
||||
<open-checksum type="sha256">a2a2c52ce2b2ce80e936a9488c8799c8508cbfe1ff5dd03187e62f8cf659ca8b</open-checksum>
|
||||
<location href="repodata/2b1d2886dec67d493adcf7358e44b7f7fd4886c85bab7fa9854014ad9c404d7a-primary.sqlite.xz"/>
|
||||
<timestamp>1674781756</timestamp>
|
||||
<size>2230076</size>
|
||||
<open-size>15314944</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="filelists_db">
|
||||
<checksum type="sha256">637abdee51be41d56603a2c031bfaf0dd4fc9da0127c826328d9a527aa3b5aa0</checksum>
|
||||
<open-checksum type="sha256">979021c34ae689ddfdd32f1a37e78da16fdb827e8bb5c0f8818ccfe880906b74</open-checksum>
|
||||
<location href="repodata/637abdee51be41d56603a2c031bfaf0dd4fc9da0127c826328d9a527aa3b5aa0-filelists.sqlite.xz"/>
|
||||
<timestamp>1674781753</timestamp>
|
||||
<size>1689576</size>
|
||||
<open-size>12529664</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="other_db">
|
||||
<checksum type="sha256">45ff5a2543dd16101778346f47e0d2362fe546698f137a05b7b72d638f03904f</checksum>
|
||||
<open-checksum type="sha256">e045ad4b00b3d20c2cd489a89297ed7c7d0efa1b279cd012b1e53dab06efef24</open-checksum>
|
||||
<location href="repodata/45ff5a2543dd16101778346f47e0d2362fe546698f137a05b7b72d638f03904f-other.sqlite.xz"/>
|
||||
<timestamp>1674781750</timestamp>
|
||||
<size>427448</size>
|
||||
<open-size>6021120</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="group">
|
||||
<checksum type="sha256">dae7e104812099a2f632ea4c5ef2769aca18ca1205abdd2c3ba6d171e319df3d</checksum>
|
||||
<location href="repodata/dae7e104812099a2f632ea4c5ef2769aca18ca1205abdd2c3ba6d171e319df3d-comps-BaseOS.x86_64.xml"/>
|
||||
<timestamp>1674781726</timestamp>
|
||||
<size>298889</size>
|
||||
</data>
|
||||
<data type="group_xz">
|
||||
<checksum type="sha256">741d3c80487757df624285f4a107f925abfac16115210486760a3920d8724e38</checksum>
|
||||
<open-checksum type="sha256">dae7e104812099a2f632ea4c5ef2769aca18ca1205abdd2c3ba6d171e319df3d</open-checksum>
|
||||
<location href="repodata/741d3c80487757df624285f4a107f925abfac16115210486760a3920d8724e38-comps-BaseOS.x86_64.xml.xz"/>
|
||||
<timestamp>1674781749</timestamp>
|
||||
<size>57068</size>
|
||||
<open-size>298889</open-size>
|
||||
</data>
|
||||
<data type="updateinfo">
|
||||
<checksum type="sha256">568de83be47822b08ea890ce0f58fd263c61c9a5c5dc500789d25e7020827112</checksum>
|
||||
<open-checksum type="sha256">1be116b93938f8bf96bb27115a63be34b59b36fcb4b2bfd3fc22c4eb3e3ffce5</open-checksum>
|
||||
<location href="repodata/568de83be47822b08ea890ce0f58fd263c61c9a5c5dc500789d25e7020827112-updateinfo.xml.gz"/>
|
||||
<timestamp>1674284973</timestamp>
|
||||
<size>56390</size>
|
||||
<open-size>508695</open-size>
|
||||
</data>
|
||||
</repomd>
|
@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<repomd xmlns="http://linux.duke.edu/metadata/repo" xmlns:rpm="http://linux.duke.edu/metadata/rpm">
|
||||
<revision>8.7</revision>
|
||||
<tags>
|
||||
<distro cpeid="cpe:/o:rocky:rocky:8">Rocky Linux 8</distro>
|
||||
</tags>
|
||||
<data type="primary">
|
||||
<checksum type="sha256">712e4af06a8f9f13766274c3fa83bbdf5572a1014ec77f7cd30d56d492a40db2</checksum>
|
||||
<open-checksum type="sha256">c3ec31964ce06e7dc14a8184ad11d6f1edce3a718bd63e4de8ed18349d27e85e</open-checksum>
|
||||
<location href="repodata/712e4af06a8f9f13766274c3fa83bbdf5572a1014ec77f7cd30d56d492a40db2-primary.xml.gz"/>
|
||||
<timestamp>1674781748</timestamp>
|
||||
<size>1791032</size>
|
||||
<open-size>13677600</open-size>
|
||||
</data>
|
||||
<data type="filelists">
|
||||
<checksum type="sha256">052aea22e07e586ae9383f6da4056599417fc445431c9d0b1136f0316ef4843e</checksum>
|
||||
<open-checksum type="sha256">dd5952122ed4335b799b1853f096f05b9e9ea6ea1a48e344700b7b82f468d61f</open-checksum>
|
||||
<location href="repodata/052aea22e07e586ae9383f6da4056599417fc445431c9d0b1136f0316ef4843e-filelists.xml.gz"/>
|
||||
<timestamp>1674781749</timestamp>
|
||||
<size>1800846</size>
|
||||
<open-size>22806093</open-size>
|
||||
</data>
|
||||
<data type="other">
|
||||
<checksum type="sha256">37421cd13a9594ff7dd3a0f2953aa19a01290e90be43db4ce279fef4394fdcd0</checksum>
|
||||
<open-checksum type="sha256">3be8a12fb7bcd600b178f6b00404d1e4e9196b9f0d5faea460c58b8d07771747</open-checksum>
|
||||
<location href="repodata/37421cd13a9594ff7dd3a0f2953aa19a01290e90be43db4ce279fef4394fdcd0-other.xml.gz"/>
|
||||
<timestamp>1674781749</timestamp>
|
||||
<size>878178</size>
|
||||
<open-size>6343206</open-size>
|
||||
</data>
|
||||
<data type="primary_db">
|
||||
<checksum type="sha256">2b1d2886dec67d493adcf7358e44b7f7fd4886c85bab7fa9854014ad9c404d7a</checksum>
|
||||
<open-checksum type="sha256">a2a2c52ce2b2ce80e936a9488c8799c8508cbfe1ff5dd03187e62f8cf659ca8b</open-checksum>
|
||||
<location href="repodata/2b1d2886dec67d493adcf7358e44b7f7fd4886c85bab7fa9854014ad9c404d7a-primary.sqlite.xz"/>
|
||||
<timestamp>1674781756</timestamp>
|
||||
<size>2230076</size>
|
||||
<open-size>15314944</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="filelists_db">
|
||||
<checksum type="sha256">637abdee51be41d56603a2c031bfaf0dd4fc9da0127c826328d9a527aa3b5aa0</checksum>
|
||||
<open-checksum type="sha256">979021c34ae689ddfdd32f1a37e78da16fdb827e8bb5c0f8818ccfe880906b74</open-checksum>
|
||||
<location href="repodata/637abdee51be41d56603a2c031bfaf0dd4fc9da0127c826328d9a527aa3b5aa0-filelists.sqlite.xz"/>
|
||||
<timestamp>1674781753</timestamp>
|
||||
<size>1689576</size>
|
||||
<open-size>12529664</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="other_db">
|
||||
<checksum type="sha256">45ff5a2543dd16101778346f47e0d2362fe546698f137a05b7b72d638f03904f</checksum>
|
||||
<open-checksum type="sha256">e045ad4b00b3d20c2cd489a89297ed7c7d0efa1b279cd012b1e53dab06efef24</open-checksum>
|
||||
<location href="repodata/45ff5a2543dd16101778346f47e0d2362fe546698f137a05b7b72d638f03904f-other.sqlite.xz"/>
|
||||
<timestamp>1674781750</timestamp>
|
||||
<size>427448</size>
|
||||
<open-size>6021120</open-size>
|
||||
<database_version>10</database_version>
|
||||
</data>
|
||||
<data type="group">
|
||||
<checksum type="sha256">dae7e104812099a2f632ea4c5ef2769aca18ca1205abdd2c3ba6d171e319df3d</checksum>
|
||||
<location href="repodata/dae7e104812099a2f632ea4c5ef2769aca18ca1205abdd2c3ba6d171e319df3d-comps-BaseOS.x86_64.xml"/>
|
||||
<timestamp>1674781726</timestamp>
|
||||
<size>298889</size>
|
||||
</data>
|
||||
<data type="group_xz">
|
||||
<checksum type="sha256">741d3c80487757df624285f4a107f925abfac16115210486760a3920d8724e38</checksum>
|
||||
<open-checksum type="sha256">dae7e104812099a2f632ea4c5ef2769aca18ca1205abdd2c3ba6d171e319df3d</open-checksum>
|
||||
<location href="repodata/741d3c80487757df624285f4a107f925abfac16115210486760a3920d8724e38-comps-BaseOS.x86_64.xml.xz"/>
|
||||
<timestamp>1674781749</timestamp>
|
||||
<size>57068</size>
|
||||
<open-size>298889</open-size>
|
||||
</data>
|
||||
<data type="updateinfo">
|
||||
<checksum type="sha256">2242022f6b5935ee22d4ba78d65da0a37873e5a42f00de907795b809d3dadb59</checksum>
|
||||
<open-checksum type="sha256">8ad9b2cab0f009a09fc6ed6f6fb946ce734e1d90d0d2ff6faf878788393ba4d8</open-checksum>
|
||||
<location href="repodata/2242022f6b5935ee22d4ba78d65da0a37873e5a42f00de907795b809d3dadb59-updateinfo.xml.gz"/>
|
||||
<timestamp>1674284973</timestamp>
|
||||
<size>1706</size>
|
||||
<open-size>8335</open-size>
|
||||
</data>
|
||||
</repomd>
|
111
apollo/tests/publishing_tools/data/updateinfo__test__1.xml
Normal file
111
apollo/tests/publishing_tools/data/updateinfo__test__1.xml
Normal file
@ -0,0 +1,111 @@
|
||||
<updates>
|
||||
<update from="releng@rockylinux.org" status="final" type="security" version="2">
|
||||
<id>RLSA-2022:1821</id>
|
||||
<title>Moderate: python27:2.7 security update</title>
|
||||
<description>Python is an interpreted, interactive, object-oriented programming language that supports modules, classes, exceptions, high-level dynamic data types, and dynamic typing. The python27 packages provide a stable release of Python 2.7 with a number of additional utilities and database connectors for MySQL and PostgreSQL.
|
||||
|
||||
Security Fix(es):
|
||||
|
||||
* python: urllib: Regular expression DoS in AbstractBasicAuthHandler (CVE-2021-3733)
|
||||
|
||||
* python: ftplib should not use the host from the PASV response (CVE-2021-4189)
|
||||
|
||||
* python-lxml: HTML Cleaner allows crafted and SVG embedded scripts to pass through (CVE-2021-43818)
|
||||
|
||||
* python: urllib.parse does not sanitize URLs containing ASCII newline and tabs (CVE-2022-0391)
|
||||
|
||||
* python: urllib: HTTP client possible infinite loop on a 100 Continue response (CVE-2021-3737)
|
||||
|
||||
For 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.
|
||||
|
||||
Additional Changes:
|
||||
|
||||
For detailed information on changes in this release, see the Rocky Linux 8.6 Release Notes linked from the References section.</description>
|
||||
<issued>2022-05-10 08:02:50</issued>
|
||||
<updated>2023-02-02 13:41:28</updated>
|
||||
<rights>Copyright 2023 Rocky Enterprise Software Foundation</rights>
|
||||
<release>Rocky Linux 8</release>
|
||||
<pushcount>1</pushcount>
|
||||
<severity>Moderate</severity>
|
||||
<summary>An update is available for python-pymongo, python2-rpm-macros, python-sqlalchemy, python-backports, python-docutils, pytest, python-psycopg2, python-lxml, python-PyMySQL, python-urllib3, PyYAML, python-pytest-mock, python-attrs, python-jinja2, python-docs, python-requests, python-mock, python-ipaddress, python-funcsigs, python2-six, python-py, python2, python2-pip, python-chardet, python-markupsafe, python-pluggy, python-pygments, python2-setuptools, Cython, python-virtualenv, babel, python-dns, python-wheel, python-pysocks, python-backports-ssl_match_hostname, python-coverage, python-setuptools_scm, pytz, python-nose, scipy, python-idna, numpy.
|
||||
This update affects Rocky Linux 8.
|
||||
A Common Vulnerability Scoring System (CVSS) base score, which gives a detailed severity rating, is available for each vulnerability from the CVE list</summary>
|
||||
<description>Python is an interpreted, interactive, object-oriented programming language that supports modules, classes, exceptions, high-level dynamic data types, and dynamic typing. The python27 packages provide a stable release of Python 2.7 with a number of additional utilities and database connectors for MySQL and PostgreSQL.
|
||||
|
||||
Security Fix(es):
|
||||
|
||||
* python: urllib: Regular expression DoS in AbstractBasicAuthHandler (CVE-2021-3733)
|
||||
|
||||
* python: ftplib should not use the host from the PASV response (CVE-2021-4189)
|
||||
|
||||
* python-lxml: HTML Cleaner allows crafted and SVG embedded scripts to pass through (CVE-2021-43818)
|
||||
|
||||
* python: urllib.parse does not sanitize URLs containing ASCII newline and tabs (CVE-2022-0391)
|
||||
|
||||
* python: urllib: HTTP client possible infinite loop on a 100 Continue response (CVE-2021-3737)
|
||||
|
||||
For 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.
|
||||
|
||||
Additional Changes:
|
||||
|
||||
For detailed information on changes in this release, see the Rocky Linux 8.6 Release Notes linked from the References section.</description>
|
||||
<solution />
|
||||
<references>
|
||||
<reference href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3733" id="CVE-2021-3733" type="cve" title="CVE-2021-3733" />
|
||||
<reference href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3737" id="CVE-2021-3737" type="cve" title="CVE-2021-3737" />
|
||||
<reference href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-4189" id="CVE-2021-4189" type="cve" title="CVE-2021-4189" />
|
||||
<reference href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-43818" id="CVE-2021-43818" type="cve" title="CVE-2021-43818" />
|
||||
<reference href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0391" id="CVE-2022-0391" type="cve" title="CVE-2022-0391" />
|
||||
<reference href="https://bugzilla.redhat.com/show_bug.cgi?id=1995162" id="1995162" type="bugzilla" title="" />
|
||||
<reference href="https://bugzilla.redhat.com/show_bug.cgi?id=1995234" id="1995234" type="bugzilla" title="" />
|
||||
<reference href="https://bugzilla.redhat.com/show_bug.cgi?id=2006792" id="2006792" type="bugzilla" title="" />
|
||||
<reference href="https://bugzilla.redhat.com/show_bug.cgi?id=2032569" id="2032569" type="bugzilla" title="" />
|
||||
<reference href="https://bugzilla.redhat.com/show_bug.cgi?id=2036020" id="2036020" type="bugzilla" title="" />
|
||||
<reference href="https://bugzilla.redhat.com/show_bug.cgi?id=2047376" id="2047376" type="bugzilla" title="" />
|
||||
<reference href="https://errata.rockylinux.org/RLSA-2022:1821" id="RLSA-2022:1821" type="self" title="RLSA-2022:1821" />
|
||||
</references>
|
||||
<pkglist />
|
||||
</update>
|
||||
<update from="releng@rockylinux.org" status="final" type="security" version="2">
|
||||
<id>RLSA-2022:7593</id>
|
||||
<title>Moderate: python27:2.7 security update</title>
|
||||
<description>Python is an interpreted, interactive, object-oriented programming language that supports modules, classes, exceptions, high-level dynamic data types, and dynamic typing.
|
||||
|
||||
Security Fix(es):
|
||||
|
||||
* python: mailcap: findmatch() function does not sanitize the second argument (CVE-2015-20107).
|
||||
|
||||
For 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.
|
||||
|
||||
Additional Changes:
|
||||
|
||||
For detailed information on changes in this release, see the Rocky Linux 8.7 Release Notes linked from the References section.</description>
|
||||
<issued>2022-11-08 06:23:47</issued>
|
||||
<updated>2023-02-02 13:52:34</updated>
|
||||
<rights>Copyright 2023 Rocky Enterprise Software Foundation</rights>
|
||||
<release>Rocky Linux 8</release>
|
||||
<pushcount>1</pushcount>
|
||||
<severity>Moderate</severity>
|
||||
<summary>An update is available for python-pymongo, python2-rpm-macros, python-sqlalchemy, python-backports, python-docutils, pytest, python-psycopg2, python-lxml, python-PyMySQL, python-urllib3, PyYAML, python-pytest-mock, python-attrs, python-jinja2, python-docs, python-requests, python-mock, python-ipaddress, python-funcsigs, python2-six, python-py, python2, python2-pip, python-chardet, python-markupsafe, python-pluggy, python-pygments, python2-setuptools, Cython, python-virtualenv, babel, python-dns, python-wheel, python-pysocks, python-backports-ssl_match_hostname, python-coverage, python-setuptools_scm, pytz, python-nose, scipy, python-idna, numpy.
|
||||
This update affects Rocky Linux 8.
|
||||
A Common Vulnerability Scoring System (CVSS) base score, which gives a detailed severity rating, is available for each vulnerability from the CVE list</summary>
|
||||
<description>Python is an interpreted, interactive, object-oriented programming language that supports modules, classes, exceptions, high-level dynamic data types, and dynamic typing.
|
||||
|
||||
Security Fix(es):
|
||||
|
||||
* python: mailcap: findmatch() function does not sanitize the second argument (CVE-2015-20107).
|
||||
|
||||
For 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.
|
||||
|
||||
Additional Changes:
|
||||
|
||||
For detailed information on changes in this release, see the Rocky Linux 8.7 Release Notes linked from the References section.</description>
|
||||
<solution />
|
||||
<references>
|
||||
<reference href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-20107" id="CVE-2015-20107" type="cve" title="CVE-2015-20107" />
|
||||
<reference href="https://bugzilla.redhat.com/show_bug.cgi?id=2075390" id="2075390" type="bugzilla" title="" />
|
||||
<reference href="https://errata.rockylinux.org/RLSA-2022:7593" id="RLSA-2022:7593" type="self" title="RLSA-2022:7593" />
|
||||
</references>
|
||||
<pkglist />
|
||||
</update>
|
||||
</updates>
|
498
apollo/tests/publishing_tools/test_apollo_tree.py
Normal file
498
apollo/tests/publishing_tools/test_apollo_tree.py
Normal file
@ -0,0 +1,498 @@
|
||||
import tempfile
|
||||
import shutil
|
||||
import pathlib
|
||||
import hashlib
|
||||
from os import path, environ
|
||||
|
||||
import pytest
|
||||
|
||||
from apollo.publishing_tools import apollo_tree
|
||||
|
||||
from common.testing import MockResponse
|
||||
|
||||
data = [
|
||||
"baseos__base__repomd__x86_64.xml",
|
||||
"baseos__base__repomd__aarch64.xml",
|
||||
"appstream__base__repomd__x86_64.xml",
|
||||
"appstream__base__repomd__aarch64.xml",
|
||||
]
|
||||
|
||||
|
||||
async def _setup_test_baseos(directory: str):
|
||||
file = data[0]
|
||||
base_dir = path.join(
|
||||
directory,
|
||||
"BaseOS/x86_64/os/repodata",
|
||||
)
|
||||
pathlib.Path(base_dir).mkdir(parents=True, exist_ok=True)
|
||||
shutil.copyfile(
|
||||
path.join(path.dirname(__file__), "data", file),
|
||||
path.join(base_dir, "repomd.xml"),
|
||||
)
|
||||
|
||||
# Run scan_path
|
||||
repos = await apollo_tree.scan_path(
|
||||
directory,
|
||||
"$reponame/$arch/os/repodata/repomd.xml",
|
||||
[],
|
||||
)
|
||||
|
||||
return repos
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_scan_path_valid_structure():
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
# Copy test data to temp dir
|
||||
for file in data:
|
||||
fsplit = file.split("__")
|
||||
base_dir = path.join(
|
||||
directory,
|
||||
fsplit[0],
|
||||
fsplit[-1].removesuffix(".xml"),
|
||||
"os/repodata",
|
||||
)
|
||||
pathlib.Path(base_dir).mkdir(parents=True, exist_ok=True)
|
||||
shutil.copyfile(
|
||||
path.join(path.dirname(__file__), "data", file),
|
||||
path.join(base_dir, "repomd.xml"),
|
||||
)
|
||||
|
||||
# Run scan_path
|
||||
repos = await apollo_tree.scan_path(
|
||||
directory,
|
||||
"$reponame/$arch/os/repodata/repomd.xml",
|
||||
[],
|
||||
)
|
||||
|
||||
assert "baseos" in repos
|
||||
assert "appstream" in repos
|
||||
assert len(repos["baseos"]) == 2
|
||||
assert len(repos["appstream"]) == 2
|
||||
|
||||
for repo in repos["baseos"]:
|
||||
assert repo["name"] == "baseos"
|
||||
assert repo["arch"] in ["x86_64", "aarch64"]
|
||||
assert repo["found_path"] == path.join(
|
||||
directory,
|
||||
"baseos",
|
||||
repo["arch"],
|
||||
"os/repodata/repomd.xml",
|
||||
)
|
||||
|
||||
for repo in repos["appstream"]:
|
||||
assert repo["name"] == "appstream"
|
||||
assert repo["arch"] in ["x86_64", "aarch64"]
|
||||
assert repo["found_path"] == path.join(
|
||||
directory,
|
||||
"appstream",
|
||||
repo["arch"],
|
||||
"os/repodata/repomd.xml",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_scan_path_multiple_formats():
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
# Copy test data to temp dir
|
||||
for file in data:
|
||||
fsplit = file.split("__")
|
||||
base_dir = path.join(
|
||||
directory,
|
||||
fsplit[0],
|
||||
fsplit[-1].removesuffix(".xml"),
|
||||
"os/repodata",
|
||||
)
|
||||
pathlib.Path(base_dir).mkdir(parents=True, exist_ok=True)
|
||||
shutil.copyfile(
|
||||
path.join(path.dirname(__file__), "data", file),
|
||||
path.join(base_dir, "repomd.xml"),
|
||||
)
|
||||
|
||||
file = data[0]
|
||||
fsplit = file.split("__")
|
||||
base_dir = path.join(
|
||||
directory,
|
||||
fsplit[0],
|
||||
"source/tree/repodata",
|
||||
)
|
||||
pathlib.Path(base_dir).mkdir(parents=True, exist_ok=True)
|
||||
shutil.copyfile(
|
||||
path.join(path.dirname(__file__), "data", file),
|
||||
path.join(base_dir, "repomd.xml"),
|
||||
)
|
||||
|
||||
# Run scan_path
|
||||
repos = await apollo_tree.scan_path(
|
||||
directory,
|
||||
"$reponame/$arch/os/repodata/repomd.xml",
|
||||
[],
|
||||
)
|
||||
|
||||
assert "baseos" in repos
|
||||
assert "appstream" in repos
|
||||
assert len(repos["baseos"]) == 2
|
||||
assert len(repos["appstream"]) == 2
|
||||
|
||||
for repo in repos["baseos"]:
|
||||
assert repo["name"] == "baseos"
|
||||
assert repo["arch"] in ["source", "x86_64", "aarch64"]
|
||||
assert repo["found_path"] == path.join(
|
||||
directory,
|
||||
"baseos",
|
||||
repo["arch"],
|
||||
"os/repodata/repomd.xml",
|
||||
)
|
||||
|
||||
for repo in repos["appstream"]:
|
||||
assert repo["name"] == "appstream"
|
||||
assert repo["arch"] in ["x86_64", "aarch64"]
|
||||
assert repo["found_path"] == path.join(
|
||||
directory,
|
||||
"appstream",
|
||||
repo["arch"],
|
||||
"os/repodata/repomd.xml",
|
||||
)
|
||||
|
||||
# Run scan_path for source
|
||||
repos = await apollo_tree.scan_path(
|
||||
directory,
|
||||
"$reponame/source/tree/repodata/repomd.xml",
|
||||
[],
|
||||
)
|
||||
|
||||
assert "baseos" in repos
|
||||
assert len(repos["baseos"]) == 1
|
||||
|
||||
for repo in repos["baseos"]:
|
||||
assert repo["name"] == "baseos"
|
||||
assert repo["arch"] == "source"
|
||||
assert repo["found_path"] == path.join(
|
||||
directory,
|
||||
"baseos",
|
||||
"source",
|
||||
"tree/repodata/repomd.xml",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_scan_path_valid_structure_arch_first():
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
# Copy test data to temp dir
|
||||
for file in data:
|
||||
fsplit = file.split("__")
|
||||
base_dir = path.join(
|
||||
directory,
|
||||
fsplit[-1].removesuffix(".xml"),
|
||||
fsplit[0],
|
||||
"os/repodata",
|
||||
)
|
||||
pathlib.Path(base_dir).mkdir(parents=True, exist_ok=True)
|
||||
shutil.copyfile(
|
||||
path.join(path.dirname(__file__), "data", file),
|
||||
path.join(base_dir, "repomd.xml"),
|
||||
)
|
||||
|
||||
# Run scan_path
|
||||
repos = await apollo_tree.scan_path(
|
||||
directory,
|
||||
"$arch/$reponame/os/repodata/repomd.xml",
|
||||
[],
|
||||
)
|
||||
|
||||
assert "baseos" in repos
|
||||
assert "appstream" in repos
|
||||
assert len(repos["baseos"]) == 2
|
||||
assert len(repos["appstream"]) == 2
|
||||
|
||||
for repo in repos["baseos"]:
|
||||
assert repo["name"] == "baseos"
|
||||
assert repo["arch"] in ["x86_64", "aarch64"]
|
||||
assert repo["found_path"] == path.join(
|
||||
directory,
|
||||
repo["arch"],
|
||||
"baseos",
|
||||
"os/repodata/repomd.xml",
|
||||
)
|
||||
|
||||
for repo in repos["appstream"]:
|
||||
assert repo["name"] == "appstream"
|
||||
assert repo["arch"] in ["x86_64", "aarch64"]
|
||||
assert repo["found_path"] == path.join(
|
||||
directory,
|
||||
repo["arch"],
|
||||
"appstream",
|
||||
"os/repodata/repomd.xml",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fetch_updateinfo_from_apollo_live():
|
||||
# This test is only run if the environment variable
|
||||
# TEST_WITH_SIDE_EFFECTS is set to 1
|
||||
if not environ.get("TEST_WITH_SIDE_EFFECTS"):
|
||||
pytest.skip("Skipping test_fetch_updateinfo_from_apollo_live")
|
||||
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
file = data[0]
|
||||
base_dir = path.join(
|
||||
directory,
|
||||
"BaseOS/x86_64/os/repodata",
|
||||
)
|
||||
pathlib.Path(base_dir).mkdir(parents=True, exist_ok=True)
|
||||
shutil.copyfile(
|
||||
path.join(path.dirname(__file__), "data", file),
|
||||
path.join(base_dir, "repomd.xml"),
|
||||
)
|
||||
|
||||
# Run scan_path
|
||||
repos = await apollo_tree.scan_path(
|
||||
directory,
|
||||
"$reponame/$arch/os/repodata/repomd.xml",
|
||||
[],
|
||||
)
|
||||
|
||||
assert "BaseOS" in repos
|
||||
assert len(repos["BaseOS"]) == 1
|
||||
|
||||
# Run fetch_updateinfo_from_apollo
|
||||
for _, repo_variants in repos.items():
|
||||
for repo in repo_variants:
|
||||
updateinfo = await apollo_tree.fetch_updateinfo_from_apollo(
|
||||
repo,
|
||||
"Rocky Linux 8 x86_64",
|
||||
)
|
||||
|
||||
assert updateinfo is not None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fetch_updateinfo_from_apollo_live_no_updateinfo():
|
||||
# This test is only run if the environment variable
|
||||
# TEST_WITH_SIDE_EFFECTS is set to 1
|
||||
if not environ.get("TEST_WITH_SIDE_EFFECTS"):
|
||||
pytest.skip(
|
||||
"Skipping test_fetch_updateinfo_from_apollo_live_no_updateinfo"
|
||||
)
|
||||
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
file = data[0]
|
||||
base_dir = path.join(
|
||||
directory,
|
||||
"BaseOS/x86_64/os/repodata",
|
||||
)
|
||||
pathlib.Path(base_dir).mkdir(parents=True, exist_ok=True)
|
||||
shutil.copyfile(
|
||||
path.join(path.dirname(__file__), "data", file),
|
||||
path.join(base_dir, "repomd.xml"),
|
||||
)
|
||||
|
||||
# Run scan_path
|
||||
repos = await apollo_tree.scan_path(
|
||||
directory,
|
||||
"$reponame/$arch/os/repodata/repomd.xml",
|
||||
[],
|
||||
)
|
||||
|
||||
assert "BaseOS" in repos
|
||||
assert len(repos["BaseOS"]) == 1
|
||||
|
||||
# Run fetch_updateinfo_from_apollo
|
||||
for _, repo_variants in repos.items():
|
||||
for repo in repo_variants:
|
||||
updateinfo = await apollo_tree.fetch_updateinfo_from_apollo(
|
||||
repo,
|
||||
"Rocky Linux 8 x86_64 NONEXISTENT",
|
||||
)
|
||||
|
||||
assert updateinfo is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fetch_updateinfo_from_apollo_mock(mocker):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
repos = await _setup_test_baseos(directory)
|
||||
|
||||
# Read data/updateinfo__test__1.xml
|
||||
with open(
|
||||
path.join(
|
||||
path.dirname(__file__), "data", "updateinfo__test__1.xml"
|
||||
),
|
||||
"r",
|
||||
encoding="utf-8",
|
||||
) as f:
|
||||
updateinfo_xml = f.read()
|
||||
|
||||
resp = MockResponse(updateinfo_xml, 200)
|
||||
mocker.patch("aiohttp.ClientSession.get", return_value=resp)
|
||||
|
||||
# Run fetch_updateinfo_from_apollo
|
||||
for _, repo_variants in repos.items():
|
||||
for repo in repo_variants:
|
||||
updateinfo = await apollo_tree.fetch_updateinfo_from_apollo(
|
||||
repo,
|
||||
"Rocky Linux 8 x86_64",
|
||||
True,
|
||||
)
|
||||
|
||||
assert updateinfo == updateinfo_xml
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_gzip_updateinfo(mocker):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
repos = await _setup_test_baseos(directory)
|
||||
|
||||
# Read data/updateinfo__test__1.xml
|
||||
with open(
|
||||
path.join(
|
||||
path.dirname(__file__), "data", "updateinfo__test__1.xml"
|
||||
),
|
||||
"r",
|
||||
encoding="utf-8",
|
||||
) as f:
|
||||
updateinfo_xml = f.read()
|
||||
|
||||
resp = MockResponse(updateinfo_xml, 200)
|
||||
mocker.patch("aiohttp.ClientSession.get", return_value=resp)
|
||||
|
||||
# Run fetch_updateinfo_from_apollo
|
||||
updateinfo = None
|
||||
for _, repo_variants in repos.items():
|
||||
for repo in repo_variants:
|
||||
updateinfo = await apollo_tree.fetch_updateinfo_from_apollo(
|
||||
repo,
|
||||
"Rocky Linux 8 x86_64",
|
||||
True,
|
||||
)
|
||||
|
||||
assert updateinfo == updateinfo_xml
|
||||
break
|
||||
|
||||
# Run gzip_updateinfo
|
||||
updateinfo_gz = await apollo_tree.gzip_updateinfo(updateinfo)
|
||||
assert updateinfo_gz is not None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_updateinfo_to_file(mocker):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
repos = await _setup_test_baseos(directory)
|
||||
|
||||
# Read data/updateinfo__test__1.xml
|
||||
with open(
|
||||
path.join(
|
||||
path.dirname(__file__), "data", "updateinfo__test__1.xml"
|
||||
),
|
||||
"r",
|
||||
encoding="utf-8",
|
||||
) as f:
|
||||
updateinfo_xml = f.read()
|
||||
|
||||
resp = MockResponse(updateinfo_xml, 200)
|
||||
mocker.patch("aiohttp.ClientSession.get", return_value=resp)
|
||||
|
||||
# Run fetch_updateinfo_from_apollo
|
||||
updateinfo = None
|
||||
for _, repo_variants in repos.items():
|
||||
for |