Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
libvirt-python
requests
peewee
fedora-distro-aliases>=1.5
#guestfs - after it is on pypi ( https://bugzilla.redhat.com/show_bug.cgi?id=1075594 )

# Test suite requirements
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def run(self):
"peewee",
"requests",
"packaging",
"fedora-distro-aliases>=1.5",
],
extras_require={"image_resolve_caching": ["requests_cache>=1.2"]},
)
54 changes: 54 additions & 0 deletions test/test_fedora.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
# Copyright 2026, Red Hat, Inc.
# License: GPL-2.0+ <http://spdx.org/licenses/GPL-2.0+>
# See the LICENSE file for more details on Licensing

"""Tests for Fedora release alias resolution via fedora-distro-aliases."""

from unittest.mock import patch

from munch import Munch

from testcloud.distro_utils import fedora


def _distro(version, version_number):
return Munch(version=version, version_number=version_number)


def _aliases(development, latest_stable):
return {
"fedora-development": development,
"fedora-latest-stable": latest_stable,
}


class TestGetFedoraReleases:
"""``get_fedora_releases`` maps fedora-distro-aliases data to the
oraculum-shaped ``{"rawhide", "branched", "stable"}`` dict."""

def _run(self, aliases):
with patch.object(fedora.config_data, "CACHE_IMAGES", False):
with patch.object(fedora, "get_distro_aliases", return_value=aliases):
return fedora.get_fedora_releases()

def test_without_branched(self):
aliases = _aliases(
development=[_distro("rawhide", "45")],
latest_stable=[_distro("44", "44")],
)
assert self._run(aliases) == {"rawhide": 45, "branched": None, "stable": 44}

def test_with_branched(self):
aliases = _aliases(
development=[_distro("44", "44"), _distro("rawhide", "45")],
latest_stable=[_distro("43", "43")],
)
assert self._run(aliases) == {"rawhide": 45, "branched": 44, "stable": 43}

def test_without_stable(self):
aliases = _aliases(
development=[_distro("rawhide", "45")],
latest_stable=[],
)
assert self._run(aliases) == {"rawhide": 45, "branched": None, "stable": None}
49 changes: 42 additions & 7 deletions testcloud/distro_utils/fedora.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import re
import requests

from fedora_distro_aliases import get_distro_aliases, Cache
from fedora_distro_aliases.cache import BadCache

from testcloud import config
from testcloud import exceptions
from testcloud.distro_utils.misc import get_requests_session
Expand All @@ -15,6 +18,38 @@
config_data = config.get_config()


def get_fedora_releases() -> dict:
"""
Resolve current Fedora rawhide/branched/stable release numbers via Bodhi
(using the fedora-distro-aliases library).

Returns a dict shaped like the old oraculum ``releases["fedora"]`` payload:
``{"rawhide": int, "branched": int | None, "stable": int | None}``.
"""
cache = None
if config_data.CACHE_IMAGES:
cache = Cache(
path="{}/fedora_distro_aliases_cache.json".format(config_data.DATA_DIR),
ttl=config_data.TRUST_DEADLINE * 60 * 60 * 24,
)

aliases = get_distro_aliases(cache=cache)

# The highest development release is Rawhide (its ``version`` is overridden to
# "rawhide" while ``version_number`` keeps the numeric value); any remaining
# development release is the branched one.
devel = aliases["fedora-development"]
rawhide = next(distro for distro in devel if distro.version == "rawhide")
branched = [distro for distro in devel if distro.version != "rawhide"]
stable = aliases["fedora-latest-stable"]

return {
"rawhide": int(rawhide.version_number),
"branched": int(branched[-1].version_number) if branched else None,
"stable": int(stable[0].version_number) if stable else None,
}


def _process_coreos_url(version: str, arch: str, platform: str) -> str:
"""
Returns an CoreOS url in either qemu or openstack format
Expand Down Expand Up @@ -78,19 +113,19 @@ def get_fedora_image_url(version: str, arch: str) -> str:

# get Fedora Cloud url
try:
oraculum_releases = session.get("https://packager-dashboard.fedoraproject.org/api/v1/releases").json()
except (ConnectionError, IndexError, requests.exceptions.JSONDecodeError):
log.error("Couldn't fetch Fedora releases from oraculum...")
fedora_releases = get_fedora_releases()
except (requests.exceptions.RequestException, BadCache, StopIteration, KeyError):
log.error("Couldn't fetch Fedora releases...")
raise exceptions.TestcloudImageError

if oraculum_releases["fedora"]["branched"] and version == str(oraculum_releases["fedora"]["branched"]):
if fedora_releases["branched"] and version == str(fedora_releases["branched"]):
version = "branched"

if not oraculum_releases["fedora"]["branched"] and version == "branched":
if not fedora_releases["branched"] and version == "branched":
log.warning("Branched release currently doesn't exist, using rawhide...")
version = "rawhide"

if version == str(oraculum_releases["fedora"]["rawhide"]):
if version == str(fedora_releases["rawhide"]):
version = "rawhide"

if version == "qa-matrix":
Expand Down Expand Up @@ -123,7 +158,7 @@ def get_fedora_image_url(version: str, arch: str) -> str:
return str(url)

if version == "latest":
version = str(oraculum_releases["fedora"]["stable"])
version = str(fedora_releases["stable"])

try:
releases = session.get("https://getfedora.org/releases.json").json()
Expand Down