From 525026061404ef09baebb85631d9af3b0a4d8930 Mon Sep 17 00:00:00 2001 From: Ani Sinha Date: Thu, 27 Jun 2024 18:38:22 +0530 Subject: [PATCH] Support metalink in yum repository config (#5444) 'metalink' config can be specified instead or along with 'baseurl' in the yum repository config. Add support for specifying metalink instead of 'baseurl'. Fixes GH-5359 Signed-off-by: Ani Sinha Co-authored-by: Ben Gray --- cloudinit/config/cc_yum_add_repo.py | 24 ++++++------ doc/examples/cloud-config-yum-repo.txt | 3 +- .../unittests/config/test_cc_yum_add_repo.py | 38 +++++++++++++++++++ 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/cloudinit/config/cc_yum_add_repo.py b/cloudinit/config/cc_yum_add_repo.py index cf3fd74a4ce..879e25c85c2 100644 --- a/cloudinit/config/cc_yum_add_repo.py +++ b/cloudinit/config/cc_yum_add_repo.py @@ -211,24 +211,22 @@ def handle(name: str, cfg: Config, cloud: Cloud, args: list) -> None: n_repo_config[k] = v repo_config = n_repo_config missing_required = 0 - for req_field in ["baseurl"]: + req_fields = ["baseurl", "metalink"] + for req_field in req_fields: if req_field not in repo_config: - LOG.warning( - "Repository %s does not contain a %s" - " configuration 'required' entry", - repo_id, - req_field, - ) missing_required += 1 - if not missing_required: - repo_configs[canon_repo_id] = repo_config - repo_locations[canon_repo_id] = repo_fn_pth - else: + + if missing_required == len(req_fields): LOG.warning( - "Repository %s is missing %s required fields, skipping!", + "Repository %s should contain atleast one of the" + " following configuration entries: %s, skipping!", repo_id, - missing_required, + ", ".join(req_fields), ) + else: + repo_configs[canon_repo_id] = repo_config + repo_locations[canon_repo_id] = repo_fn_pth + for (c_repo_id, path) in repo_locations.items(): repo_blob = _format_repository_config( c_repo_id, repo_configs.get(c_repo_id) diff --git a/doc/examples/cloud-config-yum-repo.txt b/doc/examples/cloud-config-yum-repo.txt index e8f2bbb415a..6a4037e2462 100644 --- a/doc/examples/cloud-config-yum-repo.txt +++ b/doc/examples/cloud-config-yum-repo.txt @@ -11,8 +11,9 @@ yum_repos: # Any repository configuration options # See: man yum.conf # - # This one is required! + # At least one of 'baseurl' or 'metalink' is required! baseurl: http://download.fedoraproject.org/pub/epel/testing/5/$basearch + metalink: https://mirrors.fedoraproject.org/metalink?repo=epel-$releasever&arch=$basearch&infra=$infra&content=$contentdir enabled: false failovermethod: priority gpgcheck: true diff --git a/tests/unittests/config/test_cc_yum_add_repo.py b/tests/unittests/config/test_cc_yum_add_repo.py index 1707860a19f..e6a9109ee19 100644 --- a/tests/unittests/config/test_cc_yum_add_repo.py +++ b/tests/unittests/config/test_cc_yum_add_repo.py @@ -31,6 +31,7 @@ def test_bad_config(self): "yum_repos": { "epel-testing": { "name": "Extra Packages for Enterprise Linux 5 - Testing", + # At least one of baseurl or metalink must be present. # Missing this should cause the repo not to be written # 'baseurl': 'http://blah.org/pub/epel/testing/5/$barch', "enabled": False, @@ -46,6 +47,43 @@ def test_bad_config(self): IOError, util.load_text_file, "/etc/yum.repos.d/epel_testing.repo" ) + def test_metalink_config(self): + cfg = { + "yum_repos": { + "epel-testing": { + "name": "Extra Packages for Enterprise Linux 5 - Testing", + "metalink": "http://blah.org/pub/epel/testing/5/$basearch", + "enabled": False, + "gpgcheck": True, + "gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL", + "failovermethod": "priority", + }, + }, + } + self.patchUtils(self.tmp) + self.patchOS(self.tmp) + cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) + contents = util.load_text_file("/etc/yum.repos.d/epel-testing.repo") + parser = configparser.ConfigParser() + parser.read_string(contents) + expected = { + "epel-testing": { + "name": "Extra Packages for Enterprise Linux 5 - Testing", + "failovermethod": "priority", + "gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL", + "enabled": "0", + "metalink": "http://blah.org/pub/epel/testing/5/$basearch", + "gpgcheck": "1", + } + } + for section in expected: + self.assertTrue( + parser.has_section(section), + "Contains section {0}".format(section), + ) + for k, v in expected[section].items(): + self.assertEqual(parser.get(section, k), v) + def test_write_config(self): cfg = { "yum_repos": {