public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/cobbler] rawhide: Update to 3.3.9
@ 2026-09-01  4:03 Orion Poplawski
  0 siblings, 0 replies; only message in thread
From: Orion Poplawski @ 2026-09-01  4:03 UTC (permalink / raw)
  To: git-commits

A new commit has been pushed.

Repo   : rpms/cobbler
Branch : rawhide
Commit : 22816b82182d74fd8509e110efd2b34be7e0f85e
Author : Orion Poplawski <orion@nwra.com>
Date   : 2026-08-31T20:37:26-06:00
Stats  : +2/-1012 in 4 file(s)
URL    : https://src.fedoraproject.org/rpms/cobbler/c/22816b82182d74fd8509e110efd2b34be7e0f85e?branch=rawhide

Log:
Update to 3.3.9

---
diff --git a/3945.patch b/3945.patch
deleted file mode 100644
index e75c349..0000000
--- a/3945.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 1d83bd29c253ba898ac35683258fec285d5a6529 Mon Sep 17 00:00:00 2001
-From: Orion Poplawski <orion@nwra.com>
-Date: Sat, 4 Oct 2025 19:49:26 -0600
-Subject: [PATCH] Use systemctl is-active --quiet to check status of services
- (fixes #3942)
-
----
- changelog.d/3942.fixed   | 1 +
- cobbler/actions/check.py | 2 +-
- 2 files changed, 2 insertions(+), 1 deletion(-)
- create mode 100644 changelog.d/3942.fixed
-
-diff --git a/changelog.d/3942.fixed b/changelog.d/3942.fixed
-new file mode 100644
-index 0000000000..444bdb800a
---- /dev/null
-+++ b/changelog.d/3942.fixed
-@@ -0,0 +1 @@
-+check: Use systemctl is-active --quiet to check the status of services
-diff --git a/cobbler/actions/check.py b/cobbler/actions/check.py
-index b79706aff1..5f6a3fa3bc 100644
---- a/cobbler/actions/check.py
-+++ b/cobbler/actions/check.py
-@@ -142,7 +142,7 @@ def check_service(self, status, which, notes=""):
-                     status.append("service %s is not running%s" % (which, notes))
-                     return
-         elif utils.is_systemd():
--            return_code = utils.subprocess_call("systemctl status %s > /dev/null 2>/dev/null" % which,
-+            return_code = utils.subprocess_call("systemctl is-active --quiet %s > /dev/null 2>/dev/null" % which,
-                                                 shell=True)
-             if return_code != 0:
-                 status.append("service %s is not running%s" % (which, notes))

diff --git a/cobbler-python3.13.patch b/cobbler-python3.13.patch
deleted file mode 100644
index 78847a4..0000000
--- a/cobbler-python3.13.patch
+++ /dev/null
@@ -1,972 +0,0 @@
-diff --git a/changelog.d/3842.fixed b/changelog.d/3842.fixed
-new file mode 100644
-index 00000000..6c6d6313
---- /dev/null
-+++ b/changelog.d/3842.fixed
-@@ -0,0 +1 @@
-+Fix compatibility with Python 3.13
-diff --git a/cobbler/actions/reposync.py b/cobbler/actions/reposync.py
-index c0163350..ec5745fb 100644
---- a/cobbler/actions/reposync.py
-+++ b/cobbler/actions/reposync.py
-@@ -23,9 +23,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- import logging
- import os
- import os.path
--import pipes
--import stat
-+import shlex
- import shutil
-+import stat
- from typing import Optional, Union
- 
- from cobbler import utils
-@@ -272,9 +272,9 @@ class RepoSync:
-             blended = utils.blender(self.api, False, repo)
-             flags = blended.get("createrepo_flags", "(ERROR: FLAGS)")
-             try:
--                cmd = "createrepo %s %s %s" % (" ".join(mdoptions), flags, pipes.quote(dirname))
--                utils.subprocess_call(cmd)
--            except:
-+                cmd = ["createrepo"] + mdoptions + flags + [shlex.quote(dirname)]
-+                utils.subprocess_call(cmd, shell=False)
-+            except Exception:
-                 utils.log_exc()
-                 self.logger.error("createrepo failed.")
-             del fnames[:]  # we're in the right place
-@@ -302,8 +302,19 @@ class RepoSync:
-         dest_path = os.path.join(self.settings.webdir, "repo_mirror", repo.name)
- 
-         # FIXME: wrapper for subprocess that logs to logger
--        cmd = ["wget", "-N", "-np", "-r", "-l", "inf", "-nd", "-P", pipes.quote(dest_path), pipes.quote(repo.mirror)]
--        rc = utils.subprocess_call(cmd)
-+        cmd = [
-+            "wget",
-+            "-N",
-+            "-np",
-+            "-r",
-+            "-l",
-+            "inf",
-+            "-nd",
-+            "-P",
-+            shlex.quote(dest_path),
-+            shlex.quote(repo.mirror),
-+        ]
-+        return_value = utils.subprocess_call(cmd, shell=False)
- 
-         if rc != 0:
-             raise CX("cobbler reposync failed")
-@@ -347,9 +358,14 @@ class RepoSync:
-         if flags == '':
-             flags = self.settings.reposync_rsync_flags
- 
--        cmd = "rsync %s --delete-after %s --delete --exclude-from=/etc/cobbler/rsync.exclude %s %s" \
--              % (flags, spacer, pipes.quote(repo.mirror), pipes.quote(dest_path))
--        rc = utils.subprocess_call(cmd)
-+        cmd = ["rsync"] + flags + ["--delete-after"]
-+        cmd += spacer + [
-+            "--delete",
-+            "--exclude-from=/etc/cobbler/rsync.exclude",
-+            shlex.quote(repo.mirror),
-+            shlex.quote(dest_path),
-+        ]
-+        return_code = utils.subprocess_call(cmd, shell=False)
- 
-         if rc != 0:
-             raise CX("cobbler reposync failed")
-@@ -386,10 +402,11 @@ class RepoSync:
-         if not HAS_LIBREPO:
-             raise CX("no librepo found, please install python3-librepo")
- 
--        if os.path.exists("/usr/bin/dnf"):
--            cmd = "/usr/bin/dnf reposync"
--        elif os.path.exists("/usr/bin/reposync"):
--            cmd = "/usr/bin/reposync"
-+        if os.path.exists("/usr/bin/reposync"):
-+            cmd = ["/usr/bin/reposync"]
-+        # DNF5 does not have a reposync subcommand
-+        elif os.path.exists("/usr/bin/dnf"):
-+            cmd = ["/usr/bin/dnf", "reposync"]
-         else:
-             # Warn about not having yum-utils.  We don't want to require it in the package because Fedora 22+ has moved
-             # to dnf.
-@@ -451,6 +468,11 @@ class RepoSync:
-             # Counter-intuitive, but we want the newish kernels too
-             arch = "i686"
- 
-+        cmd = self.reposync_cmd()
-+        cmd += self.rflags + [
-+            f"--repo={shlex.quote(rest)}",
-+            f"--download-path={shlex.quote(repos_path)}",
-+        ]
-         if arch != "none":
-             cmd = "%s -a %s" % (cmd, arch)
- 
-@@ -544,9 +566,11 @@ class RepoSync:
- 
-         if not has_rpm_list:
-             # If we have not requested only certain RPMs, use reposync
--            cmd = "%s %s --config=%s --repoid=%s -p %s" \
--                  % (cmd, self.rflags, temp_file, pipes.quote(repo.name),
--                     pipes.quote(repos_path))
-+            cmd += self.rflags + [
-+                f"--config={temp_file}",
-+                f"--repoid={shlex.quote(repo.name)}",
-+                f"--download-path={shlex.quote(repos_path)}",
-+            ]
-             if arch != "none":
-                 cmd = "%s -a %s" % (cmd, arch)
- 
-@@ -557,14 +581,14 @@ class RepoSync:
- 
-             use_source = ""
-             if arch == "src":
--                use_source = "--source"
--
--            # Older yumdownloader sometimes explodes on --resolvedeps if this happens to you, upgrade yum & yum-utils
--            extra_flags = self.settings.yumdownloader_flags
--            cmd = "/usr/bin/dnf download"
--            cmd = "%s %s %s --disablerepo=* --enablerepo=%s -c %s --destdir=%s %s" \
--                  % (cmd, extra_flags, use_source, pipes.quote(repo.name), temp_file, pipes.quote(dest_path),
--                     " ".join(repo.rpm_list))
-+                cmd.append("--source")
-+            cmd += [
-+                "--disablerepo=*",
-+                f"--enablerepo={shlex.quote(repo.name)}",
-+                f"-c={temp_file}",
-+                f"--destdir={shlex.quote(dest_path)}",
-+            ]
-+            cmd += repo.rpm_list
- 
-         # Now regardless of whether we're doing yumdownloader or reposync or whether the repo was http://, ftp://, or
-         # rhn://, execute all queued commands here.  Any failure at any point stops the operation.
-@@ -669,17 +693,21 @@ class RepoSync:
-             dists = ",".join(repo.apt_dists)
-             components = ",".join(repo.apt_components)
- 
--            mirror_data = "--method=%s --host=%s --root=%s --dist=%s --section=%s" \
--                          % (pipes.quote(method), pipes.quote(host), pipes.quote(mirror), pipes.quote(dists),
--                             pipes.quote(components))
-+            mirror_data = [
-+                f"--method={shlex.quote(method)}",
-+                f"--host={shlex.quote(host)}",
-+                f"--root={shlex.quote(mirror)}",
-+                f"--dist={shlex.quote(dists)}",
-+                f"--section={shlex.quote(components)}",
-+            ]
- 
-             rflags = "--nocleanup"
-             for x in repo.yumopts:
-                 if repo.yumopts[x]:
-                     rflags += " %s=%s" % (x, repo.yumopts[x])
-                 else:
--                    rflags += " %s" % x
--            cmd = "%s %s %s %s" % (mirror_program, rflags, mirror_data, pipes.quote(dest_path))
-+                    rflags.append(repo_yumoption)
-+            cmd = [mirror_program] + rflags + mirror_data + [shlex.quote(dest_path)]
-             if repo.arch == RepoArchs.SRC:
-                 cmd = "%s --source" % cmd
-             else:
-diff --git a/tests/actions/reposync_test.py b/tests/actions/reposync_test.py
-index 0bee772c..ee8d1549 100644
---- a/tests/actions/reposync_test.py
-+++ b/tests/actions/reposync_test.py
-@@ -1,251 +1,592 @@
-+"""
-+Tests that validate the functionality of the module that is responsible for repository synchronization.
-+"""
-+
- import os
--import glob
-+from pathlib import Path
-+from typing import TYPE_CHECKING, Any, Dict, List, Union
- 
- import pytest
- 
--from cobbler import enums
-+from cobbler import cexceptions, enums
-+from cobbler.actions import reposync
- from cobbler.api import CobblerAPI
--from cobbler.actions.reposync import RepoSync
- from cobbler.items.repo import Repo
--from cobbler import cexceptions
--from tests.conftest import does_not_raise
- 
-+from tests.conftest import does_not_raise
- 
--@pytest.fixture(scope="class")
--def api():
--    return CobblerAPI()
-+if TYPE_CHECKING:
-+    from pytest_mock import MockerFixture
- 
- 
--@pytest.fixture(scope="class")
--def reposync(api):
--    test_reposync = RepoSync(api, tries=2, nofail=False)
-+@pytest.fixture(name="reposync_object", scope="function")
-+def fixture_reposync_object(
-+    mocker: "MockerFixture", cobbler_api: CobblerAPI
-+) -> reposync.RepoSync:
-+    settings_mock = mocker.MagicMock()
-+    settings_mock.webdir = "/srv/www/cobbler"
-+    settings_mock.server = "localhost"
-+    settings_mock.http_port = 80
-+    settings_mock.proxy_url_ext = ""
-+    settings_mock.yumdownloader_flags = "--testflag"
-+    settings_mock.reposync_rsync_flags = "--testflag"
-+    settings_mock.reposync_flags = "--testflag"
-+    mocker.patch.object(cobbler_api, "settings", return_value=settings_mock)
-+    test_reposync = reposync.RepoSync(cobbler_api, tries=2, nofail=False)
-     return test_reposync
- 
- 
--@pytest.fixture
--def repo(api):
-+@pytest.fixture(name="repo")
-+def fixture_repo(cobbler_api: CobblerAPI) -> Repo:
-     """
-     Creates a Repository "testrepo0" with a keep_updated=True and mirror_locally=True".
-     """
--    test_repo = Repo(api)
-+    test_repo = Repo(cobbler_api)
-     test_repo.name = "testrepo0"
-     test_repo.mirror_locally = True
-     test_repo.keep_updated = True
--    api.add_repo(test_repo)
-     return test_repo
- 
- 
- @pytest.fixture
--def remove_repo(api):
-+def remove_repo(cobbler_api: CobblerAPI):
-     """
-     Removes the Repository "testrepo0" which can be created with repo.
-     """
-     yield
--    test_repo = api.find_repo("testrepo0")
--    if test_repo is not None:
--        api.remove_repo(test_repo.name)
-+    test_repo = cobbler_api.find_repo("testrepo0")
-+    if test_repo is not None and not isinstance(test_repo, list):
-+        cobbler_api.remove_repo(test_repo.name)
- 
- 
--class TestRepoSync:
--    @pytest.mark.usefixtures("remove_repo")
--    @pytest.mark.parametrize(
--        "input_mirror_type,input_mirror,expected_exception",
--        [
--            (
--                enums.MirrorType.BASEURL,
--                "http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/x86_64/os",
--                does_not_raise()
--            ),
--            (
--                enums.MirrorType.MIRRORLIST,
--                "https://mirrors.fedoraproject.org/mirrorlist?repo=rawhide&arch=x86_64",
--                does_not_raise()
--            ),
--            (
--                enums.MirrorType.METALINK,
--                "https://mirrors.fedoraproject.org/metalink?repo=rawhide&arch=x86_64",
--                does_not_raise()
--            ),
--            (
--                enums.MirrorType.BASEURL,
--                "http://www.example.com/path/to/some/repo",
--                pytest.raises(cexceptions.CX)
--            ),
-+@pytest.fixture(scope="function", autouse=True)
-+def reset_librepo():
-+    has_librepo = reposync.HAS_LIBREPO
-+    yield
-+    reposync.HAS_LIBREPO = has_librepo
-+
-+
-+def test_repo_walker(mocker: "MockerFixture", tmp_path: Path):
-+    # Arrange
-+    def test_fun(arg: Any, top: Any, names: Any):
-+        pass
-+
-+    subdir1 = tmp_path / "sub1"
-+    subdir2 = tmp_path / "sub2"
-+    subdir1.mkdir()
-+    subdir2.mkdir()
-+    spy = mocker.Mock(wraps=test_fun)
-+
-+    # Act
-+    reposync.repo_walker(tmp_path, spy, None)  # type: ignore
-+
-+    # Assert
-+    assert spy.mock_calls == [
-+        # settings.yaml is here because of our autouse fixture that we use to restore the settings
-+        mocker.call(None, tmp_path, ["settings.yaml", "sub1", "sub2"]),
-+        mocker.call(None, str(subdir1), []),
-+        mocker.call(None, str(subdir2), []),
-+    ]
-+
-+
-+@pytest.mark.parametrize(
-+    "input_has_librepo,input_path_exists_side_effect,expected_exception,expected_result",
-+    [
-+        (True, [False, True], does_not_raise(), ["/usr/bin/dnf", "reposync"]),
-+        (True, [True, False], does_not_raise(), ["/usr/bin/reposync"]),
-+        (True, [False, False], pytest.raises(cexceptions.CX), ""),
-+        (False, [False, True], pytest.raises(cexceptions.CX), ""),
-+    ],
-+)
-+def test_reposync_cmd(
-+    mocker: "MockerFixture",
-+    reposync_object: reposync.RepoSync,
-+    input_has_librepo: bool,
-+    input_path_exists_side_effect: List[bool],
-+    expected_exception: Any,
-+    expected_result: Union[List[str], str],
-+):
-+    # Arrange
-+    mocker.patch("os.path.exists", side_effect=input_path_exists_side_effect)
-+    reposync.HAS_LIBREPO = input_has_librepo
-+
-+    # Act
-+    with expected_exception:
-+        result = reposync_object.reposync_cmd()
-+
-+        # Assert
-+        assert result == expected_result
-+
-+
-+def test_run(mocker: "MockerFixture", reposync_object: reposync.RepoSync, repo: Repo):
-+    # Arrange
-+    env_vars: Dict[str, Any] = {}
-+    mocker.patch("os.makedirs")
-+    mocker.patch("os.path.isdir", return_value=True)
-+    mocker.patch(
-+        "os.path.join",
-+        side_effect=[
-+            "/srv/www/cobbler/repo_mirror",
-+            "/srv/www/cobbler/repo_mirror/%s" % repo.name,
-         ],
-     )
--    def test_reposync_yum(
--        self,
--        input_mirror_type,
--        input_mirror,
--        expected_exception,
--        api,
--        repo,
--        reposync
--    ):
--        # Arrange
--        test_repo = repo
--        test_repo.breed = enums.RepoBreeds.YUM
--        test_repo.mirror = input_mirror
--        test_repo.mirror_type = input_mirror_type
--        test_repo.rpm_list = "fedora-gpg-keys"
--        test_settings = api.settings()
--        repo_path = os.path.join(test_settings.webdir, "repo_mirror", test_repo.name)
--
--        # Act & Assert
--        with expected_exception:
--            reposync.run(test_repo.name)
--            result = os.path.exists(repo_path)
--            if test_repo.rpm_list and test_repo.rpm_list != []:
--                for rpm in test_repo.rpm_list:
--                    assert glob.glob(os.path.join(repo_path, "**", rpm) + "*.rpm", recursive=True) != []
--            assert result
--            # Test that re-downloading the metadata in .origin/repodata will not result in an error
--            reposync.run(test_repo.name)
--
--    @pytest.mark.usefixtures("remove_repo")
--    @pytest.mark.parametrize(
--        "input_mirror_type,input_mirror,input_arch,input_rpm_list,expected_exception",
-+    mocker.patch("os.environ", return_value=env_vars)
-+    mocker.patch.object(reposync_object, "repos", return_value=[repo])
-+    mocker.patch.object(reposync_object, "sync")
-+    mocker.patch.object(reposync_object, "update_permissions")
-+    reposync_object.repos = [repo]  # type: ignore
-+
-+    # Act
-+    reposync_object.run()
-+
-+    # Assert
-+    # This has to be 0 since all env vars need to be removed after reposync has run.
-+    assert len(env_vars) == 0
-+
-+
-+def test_gen_urlgrab_ssl_opts(reposync_object: reposync.RepoSync):
-+    # Arrange
-+    input_dict: Dict[str, Any] = {}
-+
-+    # Act
-+    result = reposync_object.gen_urlgrab_ssl_opts(input_dict)
-+
-+    # Assert
-+    assert isinstance(result, tuple)
-+    assert len(result) == 2
-+    # The data of the first element is kind of flexible let's skip asserting it for now
-+    assert isinstance(result[1], bool)
-+
-+
-+@pytest.mark.usefixtures("remove_repo")
-+@pytest.mark.parametrize(
-+    "input_mirror_type,input_mirror,expected_exception",
-+    [
-+        (
-+            enums.MirrorType.BASEURL,
-+            "http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/x86_64/os",
-+            does_not_raise(),
-+        ),
-+        (
-+            enums.MirrorType.MIRRORLIST,
-+            "https://mirrors.fedoraproject.org/mirrorlist?repo=rawhide&arch=x86_64",
-+            does_not_raise(),
-+        ),
-+        (
-+            enums.MirrorType.METALINK,
-+            "https://mirrors.fedoraproject.org/metalink?repo=rawhide&arch=x86_64",
-+            does_not_raise(),
-+        ),
-+    ],
-+)
-+def test_reposync_yum(
-+    mocker: "MockerFixture",
-+    input_mirror_type: enums.MirrorType,
-+    input_mirror: str,
-+    expected_exception: Any,
-+    cobbler_api: CobblerAPI,
-+    repo: Repo,
-+    reposync_object: reposync.RepoSync,
-+):
-+    # Arrange
-+    test_repo = repo
-+    test_repo.breed = enums.RepoBreeds.YUM
-+    test_repo.mirror = input_mirror
-+    test_repo.mirror_type = input_mirror_type
-+    test_repo.rpm_list = "fedora-gpg-keys"
-+    test_settings = cobbler_api.settings()
-+    repo_path = os.path.join(test_settings.webdir, "repo_mirror", test_repo.name)
-+    mocked_subprocess = mocker.patch(
-+        "cobbler.utils.subprocess_call", autospec=True, return_value=0
-+    )
-+    mocker.patch.object(
-+        reposync_object, "create_local_file", return_value="/create/local/file"
-+    )
-+    mocker.patch.object(
-+        reposync_object, "reposync_cmd", return_value=["/my/fake/dnf", "reposync"]
-+    )
-+    mocker.patch.object(reposync_object, "rflags", return_value="--fake-r-flakg")
-+    mocker.patch.object(
-+        reposync_object,
-+        "gen_urlgrab_ssl_opts",
-+        return_value=(("TODO", "TODO", "TODO"), False),
-+    )
-+    mocker.patch("os.path.exists", return_value=True)
-+    mocker.patch("shutil.rmtree")
-+    mocker.patch("os.makedirs")
-+    mocked_repo_walker = mocker.patch("cobbler.actions.reposync.repo_walker")
-+    handle_mock = mocker.MagicMock()
-+    result_mock = mocker.MagicMock()
-+    mocker.patch("librepo.Handle", return_value=handle_mock)
-+    mocker.patch("librepo.Result", return_value=result_mock)
-+
-+    # Act & Assert
-+    with expected_exception:
-+        reposync_object.yum_sync(repo)
-+
-+        mocked_subprocess.assert_called_with(
-+            [
-+                "/usr/bin/dnf",
-+                "download",
-+                "--testflag",
-+                "--disablerepo=*",
-+                f"--enablerepo={repo.name}",
-+                "-c=/create/local/file",
-+                f"--destdir={repo_path}",
-+                "fedora-gpg-keys",
-+            ],
-+            shell=False,
-+        )
-+        handle_mock.perform.assert_called_with(result_mock)
-+        assert mocked_repo_walker.call_count == 1
-+
-+
-+@pytest.mark.usefixtures("remove_repo")
-+@pytest.mark.parametrize(
-+    "input_mirror_type,input_mirror,input_arch,input_rpm_list,expected_exception",
-+    [
-+        (
-+            enums.MirrorType.BASEURL,
-+            "http://ftp.debian.org/debian",
-+            enums.RepoArchs.X86_64,
-+            "",
-+            does_not_raise(),
-+        ),
-+        (
-+            enums.MirrorType.MIRRORLIST,
-+            "http://ftp.debian.org/debian",
-+            enums.RepoArchs.X86_64,
-+            "",
-+            pytest.raises(cexceptions.CX),
-+        ),
-+        (
-+            enums.MirrorType.METALINK,
-+            "http://ftp.debian.org/debian",
-+            enums.RepoArchs.X86_64,
-+            "",
-+            pytest.raises(cexceptions.CX),
-+        ),
-+        (
-+            enums.MirrorType.BASEURL,
-+            "http://ftp.debian.org/debian",
-+            enums.RepoArchs.NONE,
-+            "",
-+            pytest.raises(cexceptions.CX),
-+        ),
-+        (
-+            enums.MirrorType.BASEURL,
-+            "http://ftp.debian.org/debian",
-+            enums.RepoArchs.X86_64,
-+            "dpkg",
-+            pytest.raises(cexceptions.CX),
-+        ),
-+    ],
-+)
-+def test_reposync_apt(
-+    mocker: "MockerFixture",
-+    input_mirror_type: enums.MirrorType,
-+    input_mirror: str,
-+    input_arch: enums.RepoArchs,
-+    input_rpm_list: str,
-+    expected_exception: Any,
-+    cobbler_api: CobblerAPI,
-+    repo: Repo,
-+    reposync_object: reposync.RepoSync,
-+):
-+    # Arrange
-+    test_repo = repo
-+    test_repo.breed = enums.RepoBreeds.APT
-+    test_repo.arch = input_arch
-+    test_repo.apt_components = "main"
-+    test_repo.apt_dists = "stable"
-+    test_repo.mirror = input_mirror
-+    test_repo.mirror_type = input_mirror_type
-+    test_repo.rpm_list = input_rpm_list
-+    test_settings = cobbler_api.settings()
-+    repo_path = os.path.join(test_settings.webdir, "repo_mirror", test_repo.name)
-+    mocked_subprocess = mocker.patch(
-+        "cobbler.utils.subprocess_call", autospec=True, return_value=0
-+    )
-+    mocker.patch("os.path.exists", return_value=True)
-+
-+    # Act
-+    with expected_exception:
-+        reposync_object.apt_sync(repo)
-+
-+        # Assert
-+        mocked_subprocess.assert_called_with(
-+            [
-+                "/usr/bin/debmirror",
-+                "--nocleanup",
-+                "--method=http",
-+                "--host=ftp.debian.org",
-+                "--root=/debian",
-+                "--dist=stable",
-+                "--section=main",
-+                repo_path,
-+                "--nosource",
-+                "-a=amd64",
-+            ],
-+            shell=False,
-+        )
-+
-+
-+@pytest.mark.usefixtures("remove_repo")
-+@pytest.mark.parametrize(
-+    "input_mirror_type,input_mirror,expected_exception",
-+    [
-+        (
-+            enums.MirrorType.BASEURL,
-+            "http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/x86_64/os/Packages/2",
-+            does_not_raise(),
-+        ),
-+        (
-+            enums.MirrorType.MIRRORLIST,
-+            "http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/x86_64/os/Packages/2",
-+            pytest.raises(cexceptions.CX),
-+        ),
-+        (
-+            enums.MirrorType.METALINK,
-+            "http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/x86_64/os/Packages/2",
-+            pytest.raises(cexceptions.CX),
-+        ),
-+    ],
-+)
-+def test_reposync_wget(
-+    mocker: "MockerFixture",
-+    input_mirror_type: enums.MirrorType,
-+    input_mirror: str,
-+    expected_exception: Any,
-+    cobbler_api: CobblerAPI,
-+    repo: Repo,
-+    reposync_object: reposync.RepoSync,
-+):
-+    # Arrange
-+    test_repo = repo
-+    test_repo.breed = enums.RepoBreeds.WGET
-+    test_repo.mirror = input_mirror
-+    test_repo.mirror_type = input_mirror_type
-+    repo_path = os.path.join(
-+        reposync_object.settings.webdir, "repo_mirror", test_repo.name
-+    )
-+    mocked_subprocess = mocker.patch(
-+        "cobbler.utils.subprocess_call", autospec=True, return_value=0
-+    )
-+    mocker.patch("cobbler.actions.reposync.repo_walker")
-+    mocker.patch.object(reposync_object, "create_local_file")
-+
-+    # Act
-+    with expected_exception:
-+        reposync_object.wget_sync(test_repo)
-+
-+        # Assert
-+        mocked_subprocess.assert_called_with(
-+            [
-+                "wget",
-+                "-N",
-+                "-np",
-+                "-r",
-+                "-l",
-+                "inf",
-+                "-nd",
-+                "-P",
-+                repo_path,
-+                input_mirror,
-+            ],
-+            shell=False,
-+        )
-+
-+
-+def test_reposync_rhn(
-+    mocker: "MockerFixture", reposync_object: reposync.RepoSync, repo: Repo
-+):
-+    # Arrange
-+    repo.mirror = "rhn://%s" % repo.name
-+    mocked_subprocess = mocker.patch(
-+        "cobbler.utils.subprocess_call", autospec=True, return_value=0
-+    )
-+    mocker.patch("os.path.isdir", return_value=True)
-+    mocker.patch("os.makedirs")
-+    mocker.patch("cobbler.actions.reposync.repo_walker")
-+    mocker.patch.object(reposync_object, "create_local_file")
-+    mocker.patch.object(
-+        reposync_object, "reposync_cmd", return_value=["/my/fake/reposync"]
-+    )
-+
-+    # Act
-+    reposync_object.rhn_sync(repo)
-+
-+    # Assert
-+    # TODO: Check this more and document how its actually working
-+    mocked_subprocess.assert_called_with(
-         [
--            (
--                enums.MirrorType.BASEURL,
--                "http://ftp.debian.org/debian",
--                enums.RepoArchs.X86_64,
--                "",
--                does_not_raise()
--            ),
--            (
--                enums.MirrorType.MIRRORLIST,
--                "http://ftp.debian.org/debian",
--                enums.RepoArchs.X86_64,
--                "",
--                pytest.raises(cexceptions.CX)
--            ),
--            (
--                enums.MirrorType.METALINK,
--                "http://ftp.debian.org/debian",
--                enums.RepoArchs.X86_64,
--                "",
--                pytest.raises(cexceptions.CX)
--            ),
--            (
--                enums.MirrorType.BASEURL,
--                "http://www.example.com/path/to/some/repo",
--                enums.RepoArchs.X86_64,
--                "",
--                pytest.raises(cexceptions.CX)
--            ),
--            (
--                enums.MirrorType.BASEURL,
--                "http://ftp.debian.org/debian",
--                enums.RepoArchs.NONE,
--                "",
--                pytest.raises(cexceptions.CX)
--            ),
--            (
--                enums.MirrorType.BASEURL,
--                "http://ftp.debian.org/debian",
--                enums.RepoArchs.X86_64,
--                "dpkg",
--                pytest.raises(cexceptions.CX)
--            ),
-+            "/my/fake/reposync",
-+            "--testflag",
-+            "--repo=testrepo0",
-+            "--download-path=/srv/www/cobbler/repo_mirror",
-         ],
-+        shell=False,
-     )
--    def test_reposync_apt(
--        self,
--        input_mirror_type,
--        input_mirror,
--        input_arch,
--        input_rpm_list,
--        expected_exception,
--        api,
--        repo,
--        reposync
--    ):
--        # Arrange
--        test_repo = repo
--        test_repo.breed = enums.RepoBreeds.APT
--        test_repo.arch = input_arch
--        test_repo.apt_components = "main"
--        test_repo.apt_dists = "stable"
--        test_repo.mirror = input_mirror
--        test_repo.mirror_type = input_mirror_type
--        test_repo.rpm_list = input_rpm_list
--        test_repo.yumopts = "--exclude=.* --include=dpkg.* --no-check-gpg --rsync-extra=none"
--        test_settings = api.settings()
--        repo_path = os.path.join(test_settings.webdir, "repo_mirror", test_repo.name)
--
--        # Act & Assert
--        with expected_exception:
--            reposync.run(test_repo.name)
--            result = os.path.exists(repo_path)
--            for rpm in ["dpkg"]:
--                assert glob.glob(os.path.join(repo_path, "**", "dpkg") + "*", recursive=True) != []
--            assert result
--
--    @pytest.mark.skip("To flaky and thus not reliable. Needs to be mocked to be of use.")
--    @pytest.mark.usefixtures("remove_repo")
--    @pytest.mark.parametrize(
--        "input_mirror_type,input_mirror,expected_exception",
-+
-+
-+def test_reposync_rsync(
-+    mocker: "MockerFixture", reposync_object: reposync.RepoSync, repo: Repo
-+):
-+    # Arrange
-+    mocked_subprocess = mocker.patch("cobbler.utils.subprocess_call", return_value=0)
-+    mocker.patch("cobbler.actions.reposync.repo_walker")
-+    mocker.patch.object(reposync_object, "create_local_file")
-+    repo_path = os.path.join(reposync_object.settings.webdir, "repo_mirror", repo.name)
-+
-+    # Act
-+    reposync_object.rsync_sync(repo)
-+
-+    # Assert
-+    mocked_subprocess.assert_called_with(
-         [
--            (
--                enums.MirrorType.BASEURL,
--                "http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/x86_64/os/Packages/2",
--                does_not_raise()
--            ),
--            (
--                enums.MirrorType.MIRRORLIST,
--                "http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/x86_64/os/Packages/2",
--                pytest.raises(cexceptions.CX)
--            ),
--            (
--                enums.MirrorType.METALINK,
--                "http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/x86_64/os/Packages/2",
--                pytest.raises(cexceptions.CX)
--            ),
--            (
--                enums.MirrorType.BASEURL,
--                "http://www.example.com/path/to/some/repo",
--                pytest.raises(cexceptions.CX)
--            ),
-+            "rsync",
-+            "--testflag",
-+            "--delete-after",
-+            "-e ssh",
-+            "--delete",
-+            "--exclude-from=/etc/cobbler/rsync.exclude",
-+            "/",
-+            repo_path,
-         ],
-+        shell=False,
-     )
--    def test_reposync_wget(
--        self,
--        input_mirror_type,
--        input_mirror,
--        expected_exception,
--        api,
--        repo,
--        reposync
--    ):
--        # Arrange
--        test_repo = repo
--        test_repo.breed = enums.RepoBreeds.WGET
--        test_repo.mirror = input_mirror
--        test_repo.mirror_type = input_mirror_type
--        test_settings = api.settings()
--        repo_path = os.path.join(test_settings.webdir, "repo_mirror", test_repo.name)
--
--        # Act & Assert
--        with expected_exception:
--            reposync.run(test_repo.name)
--            result = os.path.exists(repo_path)
--            for rpm in ["rpm"]:
--                assert glob.glob(os.path.join(repo_path, "**", "2") + "*", recursive=True) != []
--            assert result
--
--
--@pytest.mark.skip("TODO")
--def test_reposync_rhn():
-+
-+
-+def test_createrepo_walker(
-+    mocker: "MockerFixture", reposync_object: reposync.RepoSync, repo: Repo
-+):
-     # Arrange
-+    input_repo = repo
-+    input_repo.breed = enums.RepoBreeds.RSYNC
-+    input_dirname = ""
-+    input_fnames = []
-+    expected_call = ["createrepo", "--testflags", f"'{input_dirname}'"]
-+    mocked_subprocess = mocker.patch(
-+        "cobbler.utils.subprocess_call", autospec=True, return_value=0
-+    )
-+    mocker.patch(
-+        "cobbler.utils.blender",
-+        autospec=True,
-+        return_value={"createrepo_flags": "--testflags"},
-+    )
-+    mocker.patch("cobbler.utils.remove_yum_olddata")
-+    mocker.patch("cobbler.utils.subprocess_get", return_value="5")
-+    mocker.patch("cobbler.utils.get_family", return_value="TODO")
-+    mocker.patch("os.path.exists", return_value=True)
-+    mocker.patch("os.path.isfile", return_value=True)
-+    mocker.patch.object(reposync_object, "librepo_getinfo", return_value={})
-+
-     # Act
-+    reposync_object.createrepo_walker(input_repo, input_dirname, input_fnames)
-+
-     # Assert
--    assert False
-+    # TODO: Improve coverage over different cases in method
-+    mocked_subprocess.assert_called_with(expected_call, shell=False)
- 
- 
--@pytest.mark.skip("TODO")
--def test_reposync_rsync():
-+@pytest.mark.parametrize(
-+    "input_repotype,expected_exception",
-+    [
-+        (enums.RepoBreeds.YUM, does_not_raise()),
-+        (enums.RepoBreeds.RHN, does_not_raise()),
-+        (enums.RepoBreeds.APT, does_not_raise()),
-+        (enums.RepoBreeds.RSYNC, does_not_raise()),
-+        (enums.RepoBreeds.WGET, does_not_raise()),
-+        (enums.RepoBreeds.NONE, pytest.raises(cexceptions.CX)),
-+    ],
-+)
-+def test_sync(
-+    mocker: "MockerFixture",
-+    cobbler_api: CobblerAPI,
-+    reposync_object: reposync.RepoSync,
-+    input_repotype: enums.RepoBreeds,
-+    expected_exception: Any,
-+):
-     # Arrange
-+    test_repo = Repo(cobbler_api)
-+    test_repo.breed = input_repotype
-+    rhn_sync_mock = mocker.patch.object(reposync_object, "rhn_sync")
-+    yum_sync_mock = mocker.patch.object(reposync_object, "yum_sync")
-+    apt_sync_mock = mocker.patch.object(reposync_object, "apt_sync")
-+    rsync_sync_mock = mocker.patch.object(reposync_object, "rsync_sync")
-+    wget_sync_mock = mocker.patch.object(reposync_object, "wget_sync")
-+
-     # Act
-+    with expected_exception:
-+        reposync_object.sync(test_repo)
-+
-+        # Assert
-+        call_count = sum(
-+            (
-+                rhn_sync_mock.call_count,
-+                yum_sync_mock.call_count,
-+                apt_sync_mock.call_count,
-+                rsync_sync_mock.call_count,
-+                wget_sync_mock.call_count,
-+            )
-+        )
-+        assert call_count == 1
-+
-+
-+def test_librepo_getinfo(
-+    mocker: "MockerFixture", reposync_object: reposync.RepoSync, tmp_path: Path
-+):
-+    # Arrange
-+    handle_mock = mocker.MagicMock()
-+    result_mock = mocker.MagicMock()
-+    mocker.patch("librepo.Handle", return_value=handle_mock)
-+    mocker.patch("librepo.Result", return_value=result_mock)
-+
-+    # Act
-+    reposync_object.librepo_getinfo(str(tmp_path))
-+
-+    # Assert
-+    handle_mock.perform.assert_called_with(result_mock)
-+    result_mock.getinfo.assert_called()
-+
-+
-+def test_create_local_file(
-+    mocker: "MockerFixture", reposync_object: reposync.RepoSync, repo: Repo
-+):
-+    # Arrange
-+    mocker.patch("cobbler.utils.filesystem_helpers.mkdir", autospec=True)
-+    mock_open = mocker.patch("builtins.open", mocker.mock_open())
-+    input_dest_path = ""
-+    input_repo = repo
-+    input_output = True
-+
-+    # Act
-+    reposync_object.create_local_file(input_dest_path, input_repo, output=input_output)
-+
-+    # Assert
-+    # TODO: Extend checks
-+    assert mock_open.call_count == 1
-+    assert mock_open.mock_calls[0] == mocker.call("config.repo", "w", encoding="UTF-8")
-+    mock_open_handle = mock_open()
-+    assert mock_open_handle.write.mock_calls[0] == mocker.call("[testrepo0]\n")
-+    assert mock_open_handle.write.mock_calls[1] == mocker.call("name=testrepo0\n")
-+
-+
-+def test_update_permissions(
-+    mocker: "MockerFixture", reposync_object: reposync.RepoSync
-+):
-+    # Arrange
-+    mocked_subprocess = mocker.patch(
-+        "cobbler.utils.subprocess_call", autospec=True, return_value=0
-+    )
-+    path_to_update = "/my/fake/path"
-+    expected_calls = [
-+        mocker.call(["chown", "-R", "root:www", path_to_update], shell=False),
-+        mocker.call(["chmod", "-R", "755", path_to_update], shell=False),
-+    ]
-+
-+    # Act
-+    reposync_object.update_permissions(path_to_update)
-+
-     # Assert
--    assert False
-+    assert mocked_subprocess.mock_calls == expected_calls

diff --git a/cobbler.spec b/cobbler.spec
index 69d7d40..5fcad3b 100644
--- a/cobbler.spec
+++ b/cobbler.spec
@@ -8,7 +8,7 @@
 %bcond check 0
 
 Name:           cobbler
-Version:        3.3.7
+Version:        3.3.9
 Release:        %autorelease
 Summary:        Boot server configurator
 URL:            https://cobbler.github.io/
@@ -22,16 +22,10 @@ Source4:        %{name}.fc
 
 # Do not run coverage tests
 Patch0:         cobbler-nocov.patch
-# Python 3.13 support (backport of https://github.com/cobbler/cobbler/pull/3842)
-# https://bugzilla.redhat.com/show_bug.cgi?id=2335620
-Patch1:         cobbler-python3.13.patch
 # Upstream fix for reposync --tries
 # https://bugzilla.redhat.com/show_bug.cgi?id=2401605
 # Backport of https://github.com/cobbler/cobbler/pull/3378
 Patch2:         cobbler-reposync.patch
-# Use systemctl is-active to prevent some SELinux denials checking service status
-# https://bugzilla.redhat.com/show_bug.cgi?id=2353898
-Patch3:         https://github.com/cobbler/cobbler/pull/3945.patch
 BuildArch:      noarch
 
 BuildRequires: make

diff --git a/sources b/sources
index ba2585a..8806f66 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-SHA512 (cobbler-3.3.7.tar.gz) = df6570dd7c6cbe50464624267df1bbecbb29e60513bba312a6c726502d4670670f3113f24b6b7e465d0b3353c0721e6fe3725dbc4569b4f624ec2b4a29682d1a
+SHA512 (cobbler-3.3.9.tar.gz) = bf2b594b55e7d64c68319cfd9d908469e2f100da1f2921eca18adb4d129bca1f0d9db991b798e671aaac1f840faf0c9473f6fc4a2efd19bede8ce2cdee15c1a1

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-01  4:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-01  4:03 [rpms/cobbler] rawhide: Update to 3.3.9 Orion Poplawski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox